今天在学习ruby语言时,又发现一个有趣的地方,ruby语言和java语言在对私有方法的访问控制上是不同的。java是第一门我深入学习的语言,我也是通过它学习到了什么是面向对象思想。面向对象里一个重要的准则就是封装,将不能显示的隐藏起来。将域或者方法加上private就是为了达到最严格的访问控制,让其它类不能访问这个类的私有方法。注意,这里的控制是精细到类一级别上的,差不是精细到对象级别上,也就是说同一个类的不同对象是可以互相访问对方的私有方法和域的。覆盖过java.lang.Object下的equals方法的人,一定有过这样的体验,将传进来的object引用,强制转化成这个类的类型后,就可以直接访问它的私有域来比较了,当然也可以调用对方的私用方法。看下面的代码,会更明显:
private String name = "Su Long!";
private void say(String s) {
System.out.println(s);
}
public void test(PrivateMethodTest another) {
//另用同一个类的另外一个对象的私有方法,成功了?
another.say("Hello world");
System.out.println(another.name);
}
public static void main(String[] args) {
PrivateMethodTest one = new PrivateMethodTest();
PrivateMethodTest two = new PrivateMethodTest();
one.test(two);
}
}
这段程序可以没有警告地正确编译,并正常运行,不信你也试试。第一次发现这个现象时,有些意外,我以为虽然是同一个类,但是毕竟不是同一个对象呀,应该是不能访问的另一个对象的成员的,后来想一想,又觉得也许面向对象就是这样只控制到类这个级别吧。在学习ruby后,发现了不同,看看下面的代码:
private
def say s
puts s
end
public
def test another
#调用同一类另外一个对象的私有方法,成功了?
another.say "hello world"
end
end
one = PrivateMethodAccess.new
two = PrivateMethodAccess.new
one.test two
这段程序运行后得到如下错误:
<privatemethodaccess:0x593a5bc> G:/work/code/ruby/PrivateMethodAccess.rb:12:in `test'
G:/work/code/ruby/PrivateMethodAccess.rb:18
G:/work/code/ruby/PrivateMethodAccess.rb:12:in `test': private method `say' called for #</privatemethodaccess:0x593a5bc>
<privatemethodaccess:0x593a5bc> (NoMethodError)
from G:/work/code/ruby/PrivateMethodAccess.rb:18 </privatemethodaccess:0x593a5bc>
可见,同样是面向对象的ruby,是将控制精确到对象的级别上的,也就是说,一个对象不能调用另一个对象的私用方法,就算另一个对象和自己是同一个类的。我还没有读过面向对象的经典理论方面的书,不知道大牛们对这一点是如何想的。这也体现了两种语言在理念上的差异。对于java来说,类的观念非常重要,检测是以类为标准的,两个对象无论它们之间有多么像,哪是两者拥有除了构造函数和类名之外都一样的东西,也不是同一样东西;而对于ruby来说,虽然它是比较纯的面向对象的语言(所有都是对象,连基本类型都没有),但是类并不是第一位的,而能做什么才是第一位,所以ruby的访问控制也是关心另外一个对象能不能做什么。
看到了ruby,想起了python,于是有了下面的代码:
def __say(self, s):
print s
def test(self, another):
another.__say("hello world")
one = Test()
two = Test()
one.test(two)
结果我看到了那句老掉牙的话~~