我在Eloquent Ruby书中找到了这个课程。
class TextCompressor
attr_reader :unique, :index
def initialize( text )
@unique = []
@index = []
words = text.split
words.each do |word|
i = @unique.index( word )
if i
@index << i
else
@unique << word
@index << unique.size - 1
end
end
end
end
它的工作原理如下:
text = "This specification is the spec for a specification"
compressor = TextCompressor.new(text)
compressor.unique #=> ["This", "specification", "is", "the", "spec", "for", "a"]
compressor.index #=> [0, 1, 2, 3, 4, 5, 6, 1]
unique
中@index << unique.size - 1
的内容是什么,它从哪里获得了价值?compressor.unique
和compressor.index
来自attr_reader :unique, :index
,@unique
和@index
?答案 0 :(得分:4)
initialize
方法的上下文中,unique
与self.unique
相同,此处self
是实例化对象(TextCompressor.new
) self.unique
会返回@unique
变量
compressor.unique
和compressor.index
的原因来自attr_reader :unique, :index
。
此行为您设置getter(getter是查询对象的实例变量值的方法)。答案 1 :(得分:1)
@index
和@
是私有实例变量。在课堂上,你总是在attr_reader
之前。在课外,他们完全无法使用 [1] 。 attr_reader :unique, :index
是Ruby中的一个元编程函数,用于构造一个getter。以下是等效的。
def unique
@unique
end
def index
@index
end
和
attr_reader
object_name.unique
和co定义的方法是公共的,因此可以使用unique
语法在类外部访问。就像在许多语言中一样,它们也可以从类中不受限制地访问,所以如果你在类范围内,self.unique
和unique
将评估相同的东西(假设没有范围内称为unique.size
的局部变量。所以你的getUnique().getSize()
调用实际上是在调用两种方法。在Java中,它看起来像a.b
,但Ruby允许我们在许多情况下省略括号。
要记住Ruby的一个重要事项是,一般情况下,如果您执行a.b = c
或@
,则总是调用方法。 Ruby实例变量(以foo.bar
开头的东西)总是私有的,因此无法在类外直接访问它们。没有foo.bar
语法来访问Java或C ++中的公共实例变量。 @bar
始终是一种方法;它恰好可能是一个访问并返回{{1}}的值的方法。
这更符合Smalltalk的OOP视图,松散耦合的对象传递消息以交换信息。在这样的模型中,直接访问其他人的数据是没有意义的;你所能做的就是请求并等待回复。
[1] 忽略反射功能,可以绕过这些规则。