论坛首页 编程语言技术论坛

ruby 函数到底是按值传递还是按引用

浏览 17691 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (3) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-11-16  
fc_lamp 写道

[quote="sevk"]ruby里,最复杂的地方是这里吧???




 


i1 = T1.new


puts "i1.get_v1: #{i1.get_v1}" #输出 bbb in init 


puts "T1.get_v1: #{T1.get_v1}" #输出 ! aaa !


puts "i1.v1: #{i1.v1}" #输出 bbb in init


puts "i1.get2: #{i1.get2}" #输出   ! @@ v2 !


puts "i1.get3: #{i1.get3}" #输出 @@ v3 in init


puts "i1.v3: #{i1.v3}" #输出 这里是空的


puts "i1.vtest: #{i1.vtest}" #输出 vtest 


#puts "T1.vtest: #{T1.vtest}" 报错




这里涉及:self知识,类的属性读写控制(@,@@,Symbol)


恩,急等大牛。。。解达呀。。。


(此程式有部分看的懂,但越看越糊~~)

 

 

 

 

对此略懂, 简单解答下你的问题, 这块确实是ruby深入理解的关键点.

 

首先,要明白一点: Ruby一切皆对象.

 

什么意思呢? Ruby一个类也是一个对象(使用XX.class知道它的类是Class),它也具备方法(即所谓的类方法). 这个可以称之谓元类(MetaClass)

 

而Ruby中调用方法逻辑很简单:

1. 查询该对象所属类中的所有方法,如果存在调用之,如果不存在则调用父类的方法.

2. 如果回溯到顶级类,还不存在则调用method_missing, 默认抛出NoMethodError异常.

 

那分析下该输出

 

i1 = T1.new


puts "i1.get_v1: #{i1.get_v1}" #输出 bbb in init  ##i1属于类T1的实例,调用T1的方法get_v1,得到结果.


puts "T1.get_v1: #{T1.get_v1}" #输出 ! aaa ! ##这里调用T1的元类,即所写的self.get_v1, 得到 ! aaa !


puts "i1.v1: #{i1.v1}" #输出 bbb in init ##与第一个一致, 值得一提,attr_xx 系列方法是一个魔法,是Module中提供的方法,用在这里生成新的方法.


puts "i1.get2: #{i1.get2}" #输出   ! @@ v2 ! ##这个类变量输出,通过实例取得类变量的值.


puts "i1.get3: #{i1.get3}" #输出 @@ v3 in init ##同上


puts "i1.v3: #{i1.v3}" #输出 这里是空的 ## 未赋值,当然是空的. 记住在方法中self指向类,而在类中self指向元类.所以在类中使用@var赋值,这个变量属于元类而不是你期望的类.


puts "i1.vtest: #{i1.vtest}" #输出 vtest ## 
这个同之前的分析 


#puts "T1.vtest: #{T1.vtest}" 报错  ##元类不存在该方法,当然报错,你可以使用 class <<self 

#attr_reader :vtest 

#end

来打开元类的该方法,当然再赋个值,要不是空值.

 

 

这里讲的比较简单,参考: http://thinkinginruby.group.iteye.com/group/wiki/1275-class-with-the-module

 

更可以搜索Google: 关键字 Ruby MetaClass

 

如有不懂也可站内留言. Hope this helps.

 

0 请登录后投票
   发表时间:2011-11-17  

@ruby_windy
谢谢你的回复~

这个问题简化成了 @attr(实例变量)与@@attr(类中定义变量)的区别 呐?

puts "i1.get_v1: #{i1.get_v1}" #输出 bbb in init   与   puts "T1.get_v1: #{T1.get_v1}" #输出 ! aaa !   区别

 

 


puts "i1.v3: #{i1.v3}" #输出 这里是空的   与   puts "i1.vtest: #{i1.vtest}" #输出 vtest    区别

 

例如:

 

class T1
    attr_reader :vv
    @vv = 'this is vv'
    @v1 = '! aaa !' #实例变量
    @vtest = 'vtest' #实例变量 ( 在这里 可否理解为 @vtest 不属于实例变量i1)
    @@class = 'class variable' #类中定义的变量
    def initialize
        @v1 = 'bbb in init'
    end
    def get_vv
        @vv
    end
    def get_v1
        @v1
    end
    def get_test
        @vtest
    end
    def get_class_variable
        @@class
    end
    def self.get_v1
        @v1
    end
end
i1 = T1.new
puts "i1.get_v1: #{i1.get_v1}" #输出 bbb in init
puts "T1.get_v1: #{T1.get_v1}" #输出 ! aaa !
puts "i1.get_vv: #{i1.get_vv}" #输出 为空
puts "i1.get_test:#{i1.get_test}" #输出为空
puts "i1.get_class_variable:#{i1.get_class_variable}" #输出 class variable

 

 

0 请登录后投票
   发表时间:2011-11-18   最后修改:2011-11-18
fc_lamp 写道

@ruby_windy
谢谢你的回复~

这个问题简化成了 @attr(实例变量)与@@attr(类中定义变量)的区别 呐?

puts "i1.get_v1: #{i1.get_v1}" #输出 bbb in init   与   puts "T1.get_v1: #{T1.get_v1}" #输出 ! aaa !   区别

 

 


puts "i1.v3: #{i1.v3}" #输出 这里是空的   与   puts "i1.vtest: #{i1.vtest}" #输出 vtest    区别

 

例如:

 

class T1
    attr_reader :vv
    @vv = 'this is vv'
    @v1 = '! aaa !' #实例变量
    @vtest = 'vtest' #实例变量 ( 在这里 可否理解为 @vtest 不属于实例变量i1)
    @@class = 'class variable' #类中定义的变量
    def initialize
        @v1 = 'bbb in init'
    end
    def get_vv
        @vv
    end
    def get_v1
        @v1
    end
    def get_test
        @vtest
    end
    def get_class_variable
        @@class
    end
    def self.get_v1
        @v1
    end
end
i1 = T1.new
puts "i1.get_v1: #{i1.get_v1}" #输出 bbb in init
puts "T1.get_v1: #{T1.get_v1}" #输出 ! aaa !
puts "i1.get_vv: #{i1.get_vv}" #输出 为空
puts "i1.get_test:#{i1.get_test}" #输出为空
puts "i1.get_class_variable:#{i1.get_class_variable}" #输出 class variable

 

 


@attr 如果写在实例方法内,则有实例所独有,

而写在类定义中,则有类所有, 即ruby允许在类中作定义,属于谁由当时的self决定.

 

根据以上分析,所以

 

puts "i1.get_v1: #{i1.get_v1}" #输出 bbb in init 与 puts "T1.get_v1: #{T1.get_v1}" #输出 ! aaa !

区别

答: i1.get_v1 得到 bbb in init, 而 T1.get_v1得到类中定义的变量, ! aaa !

 

puts "i1.v3: #{i1.v3}" #输出 这里是空的 与 puts "i1.vtest: #{i1.vtest}" #输出 vtest

区别

答: i1.v3 要输出实例变量@v3,这在我们初始化方法中未定义,所以为空. i1.vtest 由于@vtest在initialize定义过,所以输出为 vtest

 

实际上,看似复杂,其实很简单,一定要明白不同环境下的self是指什么,那么一切就明白了.

0 请登录后投票
   发表时间:2011-12-02  
有点不喜欢ruby里的这么多符号,

还是python简洁
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics