通过方法链了解自我

Understanding self with method chaining

我正在尝试了解 Ruby 中的自我。

在下面粘贴的代码中,如果我使用

创建一个新的 Animal 实例

fox = Animal.new.name("Fox").color("red").natural_habitat("forest").specie("mammal")

然后调用

fox.to_s

如果我不在每个方法中 return 自我,它不会做任何事情。

为什么我在每个方法中都需要self?我创建一个新的Animal后变量不是已经保存了吗?

class Animal
  def name(name)
    @name = name
    self
  end
  def specie(specie)
    @specie = specie
    self 
  end
  def color(color)
    @color = color
    self 
  end
  def natural_habitat(natural_habitat)
    @natural_habitat = natural_habitat
    self 
  end
  def to_s
    "Name: #{@name}, Specie: #{@specie}, Color: #{@color}, Natural Habitat: #{@natural_habitat}"
  end
    end

在您的示例中,使用 self 作为 return 值很方便。方法 return 实例本身,以便您可以调用:

fox = Animal.new
fox.name("Fox").color("red").natural_habitat("forest").specie("mammal")

fox.name("Fox") 的值是实例本身,这就是为什么您可以在其上调用 .color("red")

此模式在 Ruby 中很少使用,在 Java 和 JavaScript 等语言中更为常见,在 jQuery 中尤为猖獗。部分原因是你在这里描述的冗长,其次是因为 Ruby 以 attr_accessorattr_writer.

的形式提供了一个方便的突变生成器

这些 accessor/mutator 双用途方法的一个问题是歧义。您的实施不完整,您无法从中读取信息。你需要的是:

def color(*color)
  case (color.length)
  when 1
    @color = color
    self
  when 0
    @color
  else
    raise ArgumentError, "wrong number of arguments (%d for 0)" % color.length
  end
end

要实现可以以两种方式使用的内容,需要大量代码:

animal.color('red')
animal_color = animal.color

如果你想使用这些,你需要编写你自己的元编程方法来生成它们,尽管我一开始就强烈反对走这条路。使用 attr_accessor 方法和选项哈希。

这是等效的 Ruby 模式:

# Up-front assignment via Hash
animal = Animal.new(
  name: 'Fox',
  color: 'red',
  natural_habitat: 'forest',
  specie: 'mammal'
)

# Assignment after the fact
animal.color = 'white'

如果 #name 方法在不调用 self 的情况下实现,就像这样:

def name(name)
  @name = name
end

此方法在调用时会 return 一个字符串。

Animal.new.name #=> returns "name of animal"

这意味着

Animal.new.name.specie

将在字符串对象上调用 #specie 方法(这可能会引发 NotImplemented 错误)而不是实现该方法的 Animal class 对象。