下面的“疯狂”是否有实际应用?
似乎这是ted
始终能够让自己回归世界的一种方式,人们会认为他们正在与ted
人交谈,他们希望以某种方式行事并成为某个年龄......但他并没有按照自己描绘的方式行事,并且正在向某个人撒谎。
当一个对象被返回并且你检查那个对象代表什么并且有能力时,'trickery'是可能的......但实际上该对象在返回之前是以另一种方式行事并能够做其他事情。
class Person
def age
21
end
def who_am_i?
puts "I am #{self} / #{object_id} and I am #{age} years old"
self
end
end
ted = Person.new
def ted.singleton_who_am_i?
class << self
def age
0
end
end
puts "I am #{self} / #{object_id} and I am #{age} years old"
self
end
puts ted.who_am_i? == ted.singleton_who_am_i?
>> I am #<Person:0x100138340> / 2148123040 and I am 21 years old
>> I am #<Person:0x100138340> / 2148123040 and I am 0 years old
>> true
答案 0 :(得分:0)
http://andrzejonsoftware.blogspot.ca/2011/02/dci-and-rails.html
在DCI中,您的数据模型根据其使用的上下文获得不同类型的行为。通常它是用object.extend完成的,但它几乎就是你在上面做的 - 利用元类。另一个例子(可能为什么会这样运作)是类在ruby中工作的方式。如果你说
class Foo
end
与说
相同Foo = Class.new
end
意味着您正在做的是将类Class的新实例分配给常量。当您在该类上定义方法时,您不希望它应用于类Class的所有实例,您只希望它在您定义的类上。所以当你说
时class Foo
def self.bar
end
end
确切地说是
class Foo
end
def Foo.bar
end
这与您在问题中谈论的原则完全相同
(对不起,如果不清楚的话)
答案 1 :(得分:0)
Ruby是一种非常动态的语言,允许您在运行时将代码注入对象。它有一些很好的用途,但它也可以使代码很难调试和理解。
查询对象以修改该对象的方法完全违反直觉。没有人会期望调用who_am_i来修改对象。
另一方面,替换这样的方法可以使单元测试类非常直接。
如果你想测试这个类在不同年龄段的行为方式,你可以在测试之前注入类似的代码。