这个有趣的主题已经有了很多答案,但我并没有找到真正的原因为什么会出现这种行为。让我试试:
早期的情况
在80年代的Smalltalk和90年代中期的Java之间,面向对象编程的概念得到了成熟。信息隐藏最初并不是面向对象的概念(首次提出于1978年),在Smalltalk中作为一个类的所有数据(字段)都是私有的,所有方法都是公共的。在90年代的众多面向对象开发中,Bertrand Meyer试图在他的里程碑式著作Object Oriented Software Construction (OOSC)中形式化大部分面向对象的概念和语言设计,此书自那时以来一直被认为是(几乎)确定性的面向对象概念和语言设计参考。
对于私有可见性的情况
根据Meyer的说法,应该将方法提供给一组定义好的类(第192-193页)。这显然提供了非常高的信息隐藏粒度,以下功能可用于classA和classB及其所有后代:
feature {classA, classB}
methodName
在
private
的情况下,他说:如果没有将类型明确声明为对其自身类可见,则无法在限定调用中访问该功能(方法/字段)。也就是说,如果
x
是一个变量,则不允许
x.doSomething()
。当然,在类本身内部允许不受限制的访问。
换句话说,要允许同一类的实例访问,必须显式地允许该类访问该方法。这有时被称为实例私有与类私有。
编程语言中的实例私有
我知道至少有两种语言目前正在使用实例私有信息隐藏,而不是类私有信息隐藏。一种是由Meyer设计的Eiffel语言,它将OO推到了极致。另一个是Ruby,现在更常见的语言。在Ruby中,
private
的意思是:
"仅对此实例私有"。
语言设计的选择
有人认为允许实例私有对于编译器来说很难。我不这么认为,因为只需要允许或禁止对方法的限定调用就相对简单。对于私有方法,如果允许
doSomething()
,但不允许
x.doSomething()
,那么语言设计者就有效地为私有方法和字段定义了仅实例可访问性。
从技术角度来看,选择一种方式或另一种方式没有理由(特别是考虑到Eiffel.NET可以使用IL来实现这一点,即使有多重继承,也没有固有的不提供此功能的原因)。
当然,这是个人口味问题,正如其他人已经提到的,没有类级别可见性的私有方法和字段会更难编写一些方法。
为什么C#只允许类封装而不允许实例封装
如果你查看关于实例封装(有时用于指代语言在实例级别上定义访问修饰符,而不是类级别)的互联网线程,这个概念经常受到批评。然而,考虑到一些现代语言使用实例封装,至少对于私有访问修饰符,这使你认为它可以并且在现代编程世界中是有用的。
然而,C#的确最关注C++和Java的语言设计。虽然Eiffel和Modula-3也在考虑范围内,但考虑到Eiffel缺少的许多特性(多重继承),我认为他们在私有访问修饰符方面选择了与Java和C++相同的路线。
如果你真的想知道为什么,你应该尝试联系Eric Lippert、Krzysztof Cwalina、Anders Hejlsberg或其他任何参与C#标准制定的人。不幸的是,在
The C# Programming Language的注释中,我找不到一个明确的说明。