关于 Java、C#、C++ 和 PHP 中访问级别的一个常见误解是它适用于对象而不是类。也就是说,(比如说)X 类的一个对象不能看到另一个 X 的私有成员。事实上,当然,访问级别是基于类的,一个 X 对象可以毫不费力地引用另一个对象的私有成员。
是否存在具有基于对象访问级别的语言?它们是替代或补充基于类的访问吗?这个特性对程序设计有什么影响?
关于 Java、C#、C++ 和 PHP 中访问级别的一个常见误解是它适用于对象而不是类。也就是说,(比如说)X 类的一个对象不能看到另一个 X 的私有成员。事实上,当然,访问级别是基于类的,一个 X 对象可以毫不费力地引用另一个对象的私有成员。
是否存在具有基于对象访问级别的语言?它们是替代或补充基于类的访问吗?这个特性对程序设计有什么影响?
Ruby 具有基于对象的访问级别。这是来自 Programming Ruby 的引用:
“受保护”和“私有”之间的区别相当微妙,并且在 Ruby 中与在大多数常见的 OO 语言中不同。如果一个方法是受保护的,它可以被定义类或其子类的任何实例调用。如果一个方法是私有的,它只能在调用对象的上下文中被调用——永远不可能直接访问另一个对象的私有方法,即使该对象与调用者属于同一个类。
这是来源:http ://whytheluckystiff.net/ruby/pickaxe/html/tut_classes.html#S4
Java 和 Ruby 之间的示例差异
爪哇
public class Main {
public static void main(String[] args) {
Main.A a1 = new A();
Main.A a2 = new A();
System.out.println(a1.foo(a2));
}
static class A
{
public String foo(A other_a)
{
return other_a.bar();
}
private String bar()
{
return "bar is private";
}
}
}
// Outputs
// "bar is private"
红宝石
class A
def foo other_a
other_a.bar
end
private
def bar
"bar is private"
end
end
a1 = A.new
a2 = A.new
puts a1.foo(a2)
# outputs something like
# in `foo': private method `bar' called for #<A:0x2ce9f44> (NoMethodError)
没有语言在语义层面支持这一点的主要原因是各种需求差异太大,无法找到一个足够大的共同点来支持这样的特性。数据隐藏本身就已经够糟糕的了,当你需要更细粒度的控制时,它只会变得更糟。
这种语言会有一些优点,例如,您可以将某些数据标记为除创建它的对象之外的任何人的私有数据(密码就是一个很好的例子:即使在同一应用程序中运行的代码也无法读取它们)。
不幸的是,这种“保护”将是肤浅的,因为在汇编程序级别,保护将不存在。为了提高效率,硬件需要支持它。在这种情况下,可能在 RAM 中的单个字节级别。这将使这样的应用程序非常安全并且非常缓慢。
在现实世界中,您会在主板上的TPM 芯片中找到它,并且以非常粗略的形式在 CPU 的 MMU 表中找到它。但这是在 4K 页面级别,而不是在字节级别。有库可以同时处理这两种情况,但这不算作“语言支持”IMO。
Java 以Security API的形式有类似的东西。您必须将有问题的代码包装在一个监护人中,该监护人询问当前SecuityManager
是否允许访问。
在 Python 中,您可以使用装饰器(用于方法和函数)或通过实现__setattr__
和__getattr__
用于字段访问来实现类似的功能。
您可以在 C# 中通过使用一些能够遍历堆栈并检查调用者是哪个对象的方法来实现这一点,如果它不是当前类则抛出异常。我不知道你为什么想要,但我想我会把它扔在那里。