Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么类实例可以更改私有成员变量?_C#_Oop_Encapsulation_Instantiation_Private Members - Fatal编程技术网

C# 为什么类实例可以更改私有成员变量?

C# 为什么类实例可以更改私有成员变量?,c#,oop,encapsulation,instantiation,private-members,C#,Oop,Encapsulation,Instantiation,Private Members,这段代码是用C语言编译的,类似的代码是用PHP编写的,但是有人能解释一下为什么otherTestClass.\u privateString可以在这里更改吗 我认为类的实例在任何情况下都不能更改私有成员变量,并且尝试访问otherTestClass.\u privateString会出现“由于保护级别而无法访问”错误 但事实并非如此,那么为什么在自己的类中实例化一个对象可以让您访问私有成员呢?应该这样做,这在一定程度上不破坏封装吗?还是我遗漏了一些明显的东西 (我不是问上面的课堂设计是否是好的

这段代码是用C语言编译的,类似的代码是用PHP编写的,但是有人能解释一下为什么
otherTestClass.\u privateString
可以在这里更改吗

我认为类的实例在任何情况下都不能更改私有成员变量,并且尝试访问
otherTestClass.\u privateString
会出现“由于保护级别而无法访问”错误

但事实并非如此,那么为什么在自己的类中实例化一个对象可以让您访问私有成员呢?应该这样做,这在一定程度上不破坏封装吗?还是我遗漏了一些明显的东西

  • (我不是问上面的课堂设计是否是好的实践,只是想知道它背后的理论。)

编辑-感谢您的回答和评论。为了澄清这一点,我还想知道能够做到这一点是否被视为一个积极的特性,或者这是否是为了更好地进行编译时检查/代码清晰性/而进行的必要权衡,因为大多数其他语言都是这样做的。在我看来,理想情况下,编译器会阻止或警告您这一点,但我远不是一个语言设计师。任何这样做的例子都可以让你做一些有用的事情(而不违反封装),否则这将是很困难或不可能的。私有成员可以访问该类(包括嵌套类型)的程序文本中的任何代码。它与您正在处理的类的哪个实例无关

我不认为这违反了封装——API仍然与实现分离,但是实现“知道”自己,不管它在看哪个实例

我相信在其他一些语言中,这不是可访问性的工作方式,但对于C#和Java来说确实如此。(Java对什么可以访问私有成员的规则略有不同,但您编写的翻译代码仍然有效。)

这是因为C#强制执行类级隐私,而不是对象级隐私

<>大多数主流语言都执行相同的策略,即C++、C++和java。我认为原因是:

1) 因为开发商已经习惯了这种政策


2) 因为对象级别的隐私会变得非常单调乏味,只会带来很少的好处。

在实例级别实现可访问性需要对每个成员变量访问进行运行时检查,而这个模型可以在编译时进行检查。@James:不一定。您可以要求私人成员只能通过“this”引用访问。这会很可怕,但也有可能。我想补充一下Jon的答案,这种类型的访问控制允许n元运算符(如equality)很容易编写。如果两个实例都没有访问其他私有成员的权限,那么实现平等运算符将困难得多。我同意Andy的观点,但仍然认为类级隐私与对象级隐私相比有一些弱点。这就是我在java中实现equals(objectother)时使用getter获取“other”对象属性的原因。显然,这并不总是可能的:(@miket2e:好的,一个非常简单的例子:它允许您使用私有成员在两个对象之间执行比较。基本上我看不出它会造成危害,而且它在语言复杂性、编译器工作和语言使用方面使生活变得更轻松。顺便说一句:您可以使用
ChangeData()
即使是
静态的
,您仍然可以访问私有成员。@ulrichb-在OP中需要注意的重要一点是,如果
ChangeData()
静态的
。作为一种不同的语言示例,在Ruby中,public是相同的,但private表示“只能由同一实例访问”,protected表示“只能从同一类访问”。继承与此无关。我不相信有必要使用“this”,就像编译器能够区分成员变量一样。例如,我认为需要为每个类的成员值使用getter方法会很乏味。事实上,这会不利于封装,因为你也会向其他类公开私有成员!@miket2e尝试用o实现一个复制构造函数或一个简单的Equals函数对象级隐私。在当前C中很简单:返回这个。_somePrivateField.Equals(其他。_somePrivateField)-如果您可以访问其他。_somePrivateField,您将如何在不添加公共getter的情况下实现此功能?@MichaelStum:将字段设置为实例私有或实例保护的一个优点是,这样做可以清楚地表明派生类可以在不违反Liskov替换原则的情况下重新使用这些字段。否则,s此重新指定用途可能会导致LSP冲突。
Equals
之类的内容可以通过使用类私有
Equals
方法来实现,该方法接受其他对象的内容(作为一组离散参数,或使用受类保护的类型),并让一个对象的public
Equals
方法将其状态传递给另一个对象的
Protected
Equals方法。
class TestClass
{
    private string _privateString = "hello";
    void ChangeData()
    {
        TestClass otherTestClass = new TestClass();
        otherTestClass._privateString = "world";
    }
}