第1 页 共1页1

今天在学习ruby语言时,又发现一个有趣的地方,ruby语言和java语言在对私有方法的访问控制上是不同的。java是第一门我深入学习的语言,我也是通过它学习到了什么是面向对象思想。面向对象里一个重要的准则就是封装,将不能显示的隐藏起来。将域或者方法加上private就是为了达到最严格的访问控制,让其它类不能访问这个类的私有方法。注意,这里的控制是精细到类一级别上的,差不是精细到对象级别上,也就是说同一个类的不同对象是可以互相访问对方的私有方法和域的。覆盖过java.lang.Object下的equals方法的人,一定有过这样的体验,将传进来的object引用,强制转化成这个类的类型后,就可以直接访问它的私有域来比较了,当然也可以调用对方的私用方法。看下面的代码,会更明显:

public class PrivateMethodTest {
	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后,发现了不同,看看下面的代码:

class PrivateMethodAccess
 
    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

这段程序运行后得到如下错误:

private method `say' called for #

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 #
(NoMethodError)
from G:/work/code/ruby/PrivateMethodAccess.rb:18

可见,同样是面向对象的ruby,是将控制精确到对象的级别上的,也就是说,一个对象不能调用另一个对象的私用方法,就算另一个对象和自己是同一个类的。我还没有读过面向对象的经典理论方面的书,不知道大牛们对这一点是如何想的。这也体现了两种语言在理念上的差异。对于java来说,类的观念非常重要,检测是以类为标准的,两个对象无论它们之间有多么像,哪是两者拥有除了构造函数和类名之外都一样的东西,也不是同一样东西;而对于ruby来说,虽然它是比较纯的面向对象的语言(所有都是对象,连基本类型都没有),但是类并不是第一位的,而能做什么才是第一位,所以ruby的访问控制也是关心另外一个对象能不能做什么。

看到了ruby,想起了python,于是有了下面的代码:

class Test():
    def __say(self, s):
        print s
 
    def test(self, another):
        another.__say("hello world")
 
one = Test()
two = Test()
one.test(two)

结果我看到了那句老掉牙的话~~

Share/Save/Bookmark

今天学ruby时看到一个非常有意思的语法糖: ruby里可以定义带有’='作后缀的方法名,而且当调用这个方法时,无论方法名的正常字符部分和’='之间有多少的空格,那些空格都会被自动去掉。比如:

def name= (s)
    puts sendname="hello"
end
 
name   = "hello"
name       ="hello"

上面的代码最后几行都会调用name=方法,这实在太有意思,如果我不是先看到这里的解释,而是先看到别人的代码,我一定会丰常糊涂!!先不对此做评论,来看看它有什么用:

class NewDog
    def initialize(breed)
        @breed = breed
    end
    attr_reader :breed, :name
 
    def name=(nm)
         @name = nm
    end
end
 
nd = NewDog.newj('Doberman')
nd.name  =  ('Benzy')
puts nd.name

哦,原来好处就是调用nam=方法,就好像直接给name赋值一样! 不过我觉得这样的语法糖并没有什么好处,还不如直接定义成set_name(nm)来得明了。也让学习这门语言的人少受些惊吓。

Share/Save/Bookmark

September 23rd, 2007ruby的开放类

动态语言ruby的类是开放的。这意味着,可以在运行时多次改变类的定义。见下面的代码:

class Test
  def say
    puts 'method: say'
  end
 
  def say2
    puts 'method: say2'
  end
 
end
 
t1 = Test.new
t1.say
t1.say2
 
puts 'Redefine class Test'
 
class Test
  def show
    puts 'method: show'
  end
 
  def say
    puts 'method: say --- new'
  end
end
 
t2 = Test.new
t2.show
t2.say
t2.say2
 
t1.say2
t1.say
t1.show

程序运行后会输出如下内容:

method: say
method: say2
Redefine class Test
method: show
method: say --- new
method: say2
method: say2
method: say --- new
method: show

注意以下几点有意思的地方

  1. 用旧的类生成的对象,在类被重新定义后,不仅保留了原来的类的方法,也具有了新的类的方法
  2. 用新的类生成的对象,不仅具有新的类的方法,也具有了旧的类的方法
  3. 新定义的类会把旧类里的同名方法给覆盖掉

由此可见,定义一个同名类的时候,就好像把原来的类扩展或者继承了一下,所有这个类的对象都会有新的类的定义。

Share/Save/Bookmark


第1 页 共1页1
© 2007 涂0实验室 | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress