BC0*_*C00 1 ruby ruby-on-rails getter-setter ruby-on-rails-3
我是ruby和编程的新手,我正在尝试掌握一些关键概念.鉴于我有一类狗,具有以下特点.
class Dog
attr_accessor :type, :popularity, :total
def initialize(type = nil)
@type = type
end
def total_dogs
Dog.count
end
def total
Dog.where(:type => self.type).size
end
def popularity
total.to_f/total_dogs
end
end
Run Code Online (Sandbox Code Playgroud)
我想要了解的是,ruby如何通过getter/setter方法将属性持久化到实例.我清楚地知道,如果我实例化一个新实例然后将属性保存到该实例,那么这些属性就绑定到该实例,因为如果我查看该对象,则属性如下所示:
@dog = Dog.new
@dog
=> #<Dog:0x007fa8689ea238 @type=nil>
Run Code Online (Sandbox Code Playgroud)
我很容易理解,当我传递@dog对象时,总是将@type属性作为nil.但是,我理解的情况是我将这个@dog对象传递给另一个类.就像我做的那样:
Owner.new(@dog)
Run Code Online (Sandbox Code Playgroud)
当我在所有者类中并且我调用@ dog.popularity时,它如何知道该实例的流行度值?在运行时,所有方法都被处理,然后该实例总是与当时的值绑定?抱歉,如果这没有意义,或者我离开了.
当你这样做
@dog = Dog.new
Run Code Online (Sandbox Code Playgroud)
你做了两件特别的事情
1)为代码当前所在的任何对象创建一个实例变量@dog
2)实例化Dog的新实例(包含其所有方法和属性)并将其引用分配给@dog
@dog是一个变量,恰好指向你在那时创建的Dog实例("类的实例",通常意思是"对象").您可以将其他变量设置为指向同一个实例,而在Ruby中,这通常是您传递数据的方式.对象包含实例变量,这些实例变量指向更多对象.
使用赋值运算符(即"="),您可以将变量指向任何其他对象.
要依次回答您的问题:
当我在所有者类中并且我调用@ dog.popularity时,它如何知道该实例的流行度值?
您必须小心使用Ruby(以及一般的OO语言)来区分描述和问题中的类和对象.Ruby我假设您指的是Owner类中的一行代码,并且您打算使用所有者对象.我还假设@dog是您添加到所有者的属性.
在这种情况下,Ruby知道因为@dog指向您添加到所有者的Dog对象.每个Dog对象都有自己的所有Dog实例变量的副本.你确实需要在Ruby中小心,因为变量指向对象,你不是简单地将同一个Dog对象传递给所有的所有者(即它们都有效地共享一只狗).因此,您需要了解何时创建新实例(通过新实例)以及何时只是处理现有引用.
在运行时,所有方法都被处理,然后该实例总是与当时的值绑定?
不可以.在运行时,基本的Ruby只会执行您编码的分配.在分配了分配它们的代码之前,实例变量甚至可能不存在.如果你使用attr_reader等方法,那么变量至少会存在(但除非你在初始化期间分配一些东西,否则它们将是nil)