我正在使用super
将参数传递给父initialize
方法,默认情况下不会调用该方法。这就是它的样子。 (注意在最后两个参数上使用super
)
module Pet
def initialize name, is_pet
@is_pet = is_pet
if is_pet
@name = name
else
@name = "Unnamed"
end
end
def pet?
return @is_pet
end
def get_name
return @name
end
end
class Dog
include Pet
def initialize tricks, name, is_pet
@tricks = tricks
super name, is_pet
end
def get_tricks
return @tricks
end
end
这是我能用它做的事情:
d = Dog.new ["roll", "speak", "play dead"], "Spots", true
d.pet? #=> true
d.get_tricks #=> ["roll", "speak", "play dead"]
d.get_name #=> "Spots"
它工作正常,但我只是想知道是否有更好的方法来做到这一点。
答案 0 :(得分:1)
将"Unnamed"
之类的固定字符串硬编码为@name
的值并不是一个好的编程习惯。在这种情况下,您应该分配nil
,并在打印时对其进行任何修改。假设你这样做。
然后可以从is_pet
是否name
推断nil
,因此将其作为实例变量是多余的。您只需将!!
应用于name
即可获得is_pet
。因此,你应该摆脱这样的实例变量。
您有get_
前缀作为getter方法,但在Ruby中,更好的做法是将实例变量(没有atmark)与getter名称相同。
这会给你:
module Pet
attr_reader :name
def initialize name; @name = name end
end
class Dog
include Pet
attr_reader :tricks
def initialize tricks, name
@tricks = tricks
super(name)
end
end
d = Dog.new ["roll", "speak", "play dead"], "Spots"
d.tricks #=> ["roll", "speak", "play dead"]
d.name #=> "Spots"
!!d.name #=> true (= `is_pet`)
答案 1 :(得分:0)
不要编写调用super
的代码进入包含的模块。不要编写期望孩子们打电话给超级的模块。这不是模块的重点。
不要问什么是什么,这是一个很好的面向对象的风格。查找“告诉,不要问”和鸭子打字一般。
如果要提供默认的initialize
方法,可能需要继承。但是偶尔会有一些有效的用例来覆盖模块中的初始化。这里惯用的事情是一个钩子方法:
module Pet
def initialize(options = {})
@name = options[:name]
post_initialize(options)
end
def post_initialize(options = {})
# can be overridden in including modules
end
end
class Dog
include Pet
def post_initialize(options = {})
@tricks = options[:tricks]
end
end
dog = Dog.new(name: "Fido", tricks: ["play dead", "roll over"])
模块用于在许多不同的事物中包含一些共享行为。很好地将它视为一个形容词,描述你可以用包含它的类做什么。以“-able”结尾的单词(如Enumerable
或Comparable
),描述接收类,或“-or”(Iterator
,Interactor
),描述一下上课,是模块的好选择。