如果我可以在自己的方法中更改对象的类,那将会很棒:
class Dog < Animal
def initialize(color, size)
#do some stuff
end
def do_lots_of_stuff
#really long involved calculations with different classes and methods
#and objects that I can't really change at this point
if random_condition
self = Super_Special_Dog.new(@color, @size, specialness)
end
end
end
class Super_Special_Dog < Dog
def initialize(color, size, specialness)
#do stuff
end
end
有没有办法将Dog
的实例,比如说fido&#39;转换为Super_Special_Dog
,以便在调用fido.do_lots_of_stuff
之后fido.is_a? Super_Special_Dog
将返回true
,其他方法/类可以使用Super_Special_Dog
的方法和变量对fido进行操作吗?
我尝试了上述结构并收到错误Can't change the value of self (SyntaxError)
。我可以根据Super_Special_Dog
或Dog
根据我的需要制作Animal
。
我可以看到一些关于将对象转换为自己的方法之外的其他问题,但我需要在内部进行。我已经有大约2k-3k的代码行交织在一起,此时很难改变。
答案 0 :(得分:2)
首先,没有人应该关心fido是Dog
还是Super_Special_Dog
- 他们应该只关心fido能做什么技巧(也就是说,他回答的是什么方法)。这是鸭子打字(狗打字?)做事的方式。
如果删除了需要更改实际类的要求,那么从内部向实例添加新功能是微不足道的。
class Dog
def become_special
@special = true
extend SpecialTraits
end
end
module SpecialTraits
def do_special_thing
end
end
fido = Dog.new
rex = Dog.new
fido.become_special
fido.do_special_thing # Okay!
rex.do_special_thing # NoMethodError
答案 1 :(得分:1)
您无法更改对象的类,但可以混合使用其他模块和方法。有很多方法可以做到这一点;一种方法是通过向单个实例添加单例方法。
您可以使用Object#define_singleton_method在特定实例上动态定义方法。例如:
class Dog; end
rover = Dog.new
spot = Dog.new
fido = Dog.new
# Give Rover and Spot a new method dynamically.
[rover, spot].each do |dog|
dog.define_singleton_method(:bark) { 'Woof! Woof!' }
end
# Only Rover and Spot have the new method; Fido is a barkless dog.
[rover, spot, fido].map { |dog| dog.respond_to? :bark }
#=> [true, true, false]