Ruby class 方法的说明

Clarification on Ruby class method

我从 Eloquent Ruby 书中找到了这个 class。

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]
  1. @index << unique.size - 1 中的 unique 是什么,它的值是从哪里得到的?
  2. compressor.uniquecompressor.index 是来自 attr_reader :unique, :index,还是 @unique@index

@unique@index是私有实例变量。在 class 中,您总是在它们前面加上 @。在class之外,它们是完全不可用的[1]attr_reader 是 Ruby 中的一个元编程函数,它构造了一个 getter。以下是等价的。

attr_reader :unique, :index

def unique
  @unique
end

def index
  @index
end

attr_reader 和 co 定义的方法是 public,因此可以使用 object_name.unique 语法在 class 之外访问。像在许多语言中一样,它们也可以从 class 内不合格地访问,所以如果你在 class 范围内,uniqueself.unique 将评估为相同事情(假设范围内没有名为 unique 的局部变量)。所以你的 unique.size 调用实际上是在调用两个方法。在 Java 中,它看起来像 getUnique().getSize(),但 Ruby 让我们在许多情况下可以省略括号。

关于 Ruby 需要记住的一件重要事情是,一般来说,如果您 a.ba.b = c,您总是 调用一个方法。 Ruby 实例变量(以 @ 开头的东西)始终是私有的,因此无法在 class 之外直接访问它们。没有像 Java 或 C++ 那样的 foo.bar 语法来访问 public 实例变量。 foo.bar 始终是一种方法;它可能恰好是一种访问 returns @bar.

值的方法

这更符合 Smalltalk 的 OOP 观点,松散耦合的对象传递消息以交换信息。在这样的模型中,直接访问其他人的数据是没有意义的;您所能做的就是请求它并等待响应。


[1]忽略反射特性,可以绕过此类规则

  1. initialize 方法的上下文中,uniqueself.unique 相同,这里的 self 是实例化对象 (TextCompressor.new)

self.unique 在这种情况下将 return 你 @unique 变量的值

  1. 您可以调用 compressor.uniquecompressor.index 的原因来自 attr_reader :unique, :index。 这一行为你设置了getters(getter是一种查询对象实例变量值的方法)。