第一次在堆栈溢出。
我正在研究使用Ruby或Python提供的一些元编程功能,但首先我需要知道它们在多大程度上允许我扩展语言。我需要做的主要事情是重写Class的概念。这并不意味着我想在运行时重写特定的类,而是想对类是什么进行自己的概念化。为了在这里更加具体,我想做一些类似于人们通常所说的Class的事情,但是我想遵循“open world”的假设。在普通类的“封闭世界”中,如果我将Poodle声明为Dog的子类,则是Animal的子类,那么我知道Poodle也不会是FurCoat的一种。但是,在开放世界的类中,我定义的 Poodle 对象可能是,也可能不是FurCoat类型的对象,直到我解释说我可以戴 Poodle 时,我们才能确定。 (可怜的狮子狗。)所有这一切都与我正在进行的有关OWL本体的研究有关。
请注意,我已经尝试过在线查找信息,但是由于这里的术语过多,所以我没有发现任何有用的信息。
super 谢谢
约翰
更新:我只是想到了开放类的概念的一个很好的用例。也许这将使我更好地理解自己真正想做的事情。我希望能够“描述”一个类而不是定义它。例如,我想说一个狗是a)有四只腿b)吠叫的东西。然后,我希望能够创建一个未指定Class的对象,并描述该对象有四个分支。此时,对象仍然是未指定的类型。然后,我想说的是物体吠叫。在这一点上,该物体将被认为是(可能是)一只狗。
最佳答案
我同意萨米尔(Samir)的说法,这听起来像鸭子打字。您不需要关心对象实际上是什么“类型”,只需要关心对象可以“做什么”。在Ruby和Python中都是如此。
但是,如果您确实要检查类的类型,并且确实确实需要在运行时也有一个Poodle
对象(也可以是FurCoat
),那么在Ruby中,这样做的方法是将FurCoat
模块混入Poodle
对象,如下所示:
class Poodle; end
module FurCoat; def wear; end; end
my_poodle = Poodle.new
my_poodle.is_a?(Poodle) #=> true
my_poodle.is_a?(FurCoat) #=> false
my_poodle.wear #=> NoMethodError
# now we mix in the FurCoat module
my_poodle.extend(FurCoat)
# my_poodle is now also a FurCoat
my_poodle.is_a?(Poodle) #=> true (still)
my_poodle.is_a?(FurCoat) #=> true
my_poodle.wear #=> the wear method now works
编辑(由于您的问题已更新):
您仍然不需要重写
Class
即可实现所需的功能,只需要在Ruby的kind_of?
模块上对is_a?
和instance_of?
(以及可能的Kernel
)方法进行猴子补丁。由于Ruby具有开放类,因此很容易做到:class Module
def obj_implements_interface?(obj)
false
end
end
module Kernel
alias_method :orig_is_a?, :is_a?
def is_a?(klass)
orig_is_a?(klass) || klass.obj_implements_interface?(self)
end
end
然后为每个类(或模块)定义对象实现其接口(interface)的含义:
class Dog
def self.obj_implements_interface?(obj)
obj.respond_to?(:bark) && obj.respond_to?(:num_legs) && obj.num_legs == 4
end
end
module FurCoat
def self.obj_implements_interface?(obj)
obj.respond_to?(:wear)
end
end
现在测试一下:
my_poodle = Poodle.new
my_poodle.is_a?(FurCoat) #=> false
# now define a wear method on my_poodle
def my_poodle.wear; end
my_poodle.is_a?(FurCoat) #=> true