Ruby(2.5)中是否有办法以相同的方式调用包含模块中定义的方法super
用于继承?
我的意思是,假设我有以下
class Parent
def name
"parent"
end
end
class Child < Parent
def name
"my parent is #{super}"
end
end
当我致电Child.new.name
时,我会my parent is parent
。
如何在以下情况下实现相同目标?
module Parent
def name
"parent"
end
end
class Child
include Parent
def name
"my parent is #{???}"
end
end
我应该将???
替换为什么?
谢谢
答案 0 :(得分:6)
您仍然可以使用super
:
module Parent
def name
"parent"
end
end
class Child
include Parent
def name
"my parent is #{super}"
end
end
Child.new.name # => "my parent is parent"
当包含模块时,ruby会将此模块添加到继承链。
Child.ancestors # => [Child, Parent, Object, Kernel, BasicObject]
因此,在super
中调用Child
将调用其祖先中的相应方法。
答案 1 :(得分:2)
我们获得了模块Parent
:
module Parent
def name
"parent"
end
end
和班级Child
:
class Child
include Parent
def name
"my parent is #{super}"
end
end
正如@Tai指出的那样,我们可以使用super
来获取:
Child.new.name
#=> "my parent is parent"
,因为
Child.ancestors
#=> [Child, Parent, Object, Kernel, BasicObject]
模块Parent
在什么意义上是Child
类的“父”?是的,这些只是单词,但它具有误导性。
现在让我们创建另一个模块并让Child
包含它。
module A
def name
"A"
end
end
Child.include A
Child.new.name
#=> "my parent is A"
,因为
Child.ancestors
#=> [Child, A, Parent, Object, Kernel, BasicObject]
我们看到将Class#name
定义如下更为清楚:
def name
"the last module included is #{super}"
end
让我们再试一次:使用Module#prepend。
module B
def name
"B"
end
end
Child.prepend B
Child.new.name
#=> "B"
不“我的父母是B”,因为
Child.ancestors
#=> [B, Child, A, Parent, Object, Kernel, BasicObject]
表示B#name
(不调用super
)已执行(不是Child#name
)。这意味着如果已经预先安装了任何模块,结果就毫无意义。