我希望通过继承基类来提供一致的接口。但是该基类的某些方法我想用其他功能包装。
假设每个子类都有一个eat方法:
class ClassyAnimal
def self.inherited(base)
base.class_eval do
alias :eat_without_napkin :eat
alias :eat :eat_with_napkin
end
end
def eat_with_napkin
begin
eat_without_napkin
rescue FoodOutOfMouthError
puts 'phew!'
end
end
def eat
raise 'Please implement the #eat method.'
end
end
class ClassyWalrus < ClassyAnimal
def eat
puts 'Eating Cronuts.'
raise FoodOutOfMouthError.new('Damn these tusks!')
puts 'Finishing my meal.'
end
end
class FoodOutOfMouthError < StandardError; end
现在我希望ClassyWalrus.new.eat
输出以下内容:
Eating Cronuts.
phew!
不幸的是,我们得到以下信息:
Eating Cronuts.
FoodOutOfMouthError: Damn these tusks!
在继承时,因此在alias
时,#eat被定义为ClassyAnimal中的一个而不是ClassyWalrus中的一个。别名#eat然后被子类覆盖,并且包装丢失。
可以做些什么?
答案 0 :(得分:1)
尝试以下代码添加。
课程ClassyAnimal
中的:
def eat_with_napkin
begin
yield
rescue FoodOutOfMouthError
puts 'phew!'
end
end
课程ClassyWalrus
中的:
def eat
puts 'Eating Cronuts.'
superclass.eat do
raise FoodOutOfMouthError.new('Damn these tusks!')
end
puts 'Finishing my meal.'
end
答案 1 :(得分:0)
我想到的一种可能性,我相信ActionMailer是如何做到的,是将子方法定义为实例变量,但是在类本身上调用它。
这不是我正在寻找的,所以我不接受这个答案,只是为了记录它。
class ClassyAnimal
def self.eat
if instance_methods.include? :eat
begin
self.new.eat
rescue FoodOutOfMouthError
puts 'phew!'
end
end
end
end
class ClassyWalrus < ClassyAnimal
def eat
puts 'Eating Cronuts.'
raise FoodOutOfMouthError.new('Damn these tusks!')
puts 'Finishing my meal.'
end
end
class FoodOutOfMouthError < StandardError; end
将被称为:
ClassyWalrus.eat
# outputs => Eating Cronuts.
# outputs => phew!