我被困在这里,因为我担心从父类调用子类的类方法是否是最佳做法?
module Zoo
class Animals
class << self
def update
if self.whatever == ... # Calls method 'whatever' from Tiger class
# do sth.
end
end
end
end
class Tiger < Animals
def update
super
end
class << self
def whatever
"whatever from tiger class"
end
end
end
end
Zoo::Tiger.update
它有效,但我希望能更好地解决这个问题。我想尽可能多地遵循最佳实践解决方案,这与某些自定义黑客不同。
提前感谢!
非常正常的模式。然后,您可以在每个子类中以不同的方式实现whatever
,而无需在每个子类中重新实现update
。我要补充的是:
def self.whatever
raise NotImplementedError, 'Class must implement whatever' # or some useful message
end
到Animal
类。这样,如果您从未实现whatever
的子类调用ChildClass.update
,则会出现一个有用的错误。
试试这个:
class Animals
def self.update
puts "self = #{self} in Animals::update"
if whatever == "Happy Days"
puts "The Fonz rules"
end
end
end
class Tiger < Animals
def self.whatever
"Happy Days"
end
end
Tiger.update
# self = Tiger in Animals::update
# The Fonz rules
在讨论这个问题之前,需要注意几点:
- 我已经删除了模块
Zoo
和实例方法Tiger#update
因为它们与问题无关。 - 我已经从
self.whatever
中删除了self.
,因为它不是必需的(如果没有明确的接收器,则假设self
(。 - 我以更传统的方式定义了类方法(但 OP 定义它们的方式没有错(。
-
update
只能从子类调用,因为Animal.update
会引发"没有方法或局部变量'随便'"异常。
这里重要的一点是Tiger.update
调用方法Animal::update
,就好像update
是在Tiger
中定义的,而不是从Animal
继承的。这就是为什么:
Tiger.methods.include?(:update) #=> true
因此,"从父类调用子类的类方法"是不正确的; 正在从子类调用Tiger::whatever
。没有从父类调用任何内容self
因为调用父类时永远不会等于Animals
Tiger::update
。这不仅仅是语义。