通过方法链了解自我
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_accessor
或 attr_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 对象。
我正在尝试了解 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_accessor
或 attr_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 对象。