在Ruby或Python中可以重写Class的概念吗?

JnB*_*ymn 9 ruby python metaprogramming class ontology

第一次堆栈溢出.

我正在研究使用Ruby或Python提供的一些元编程功能,但首先我需要知道它们允许我扩展语言的程度.我需要做的主要是重写Class的概念.这并不意味着我要重写一个特定的过程中运行时类,而是我要让我自己的一个什么概念的.要想在这里变得更加具体,我想做一些人们通常称之为课堂的东西,但我想要遵循一个" 开放的世界""假设.在正常类的"封闭世界"中,如果我声称Poodle是Dog的子类是Animal的子类,那么我知道Poodle也不会是一种FurCoat.但是,在开放世界类,然后我定义的Poodle对象可能是也可能不是FurCoat类型的对象,我们不会确切知道,直到我解释我可以穿长卷毛狗.(可怜的贵宾犬.)这一切都要做我正在做一项关于OWL本体的研究.

你知道,我试图在网上找到信息,但由于这里的条款超载,我没有发现任何有用的信息.

非常感谢,约翰

更新:我刚想到了一个很好的用例,用于我的开放世界的Class概念.也许这将更好地理解我真正想做的事情.我希望能够"描述"一个类而不是定义它.例如,我想能够说狗是a)有四条腿b)树皮的东西.然后我希望能够创建一个未指定Class的对象,并描述该对象有四条腿.此时,对象仍然是未指定的类型.然后我想说对象吠叫.此时,将知道该对象(可能除其他外)是狗.

Sam*_*war 8

听起来像鸭子打字给我.只需声明您想要的方法,并记住请求宽恕比允许更容易:

try:
    poodle.wear()
except (AttributeError, TypeError):
    pass
Run Code Online (Sandbox Code Playgroud)


hor*_*guy 7

我同意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
Run Code Online (Sandbox Code Playgroud)

编辑(由于您更新的问题):

你仍然不需要重写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
Run Code Online (Sandbox Code Playgroud)

然后为每个类(或模块)定义对象实现其接口的含义:

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
Run Code Online (Sandbox Code Playgroud)

现在测试一下:

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
Run Code Online (Sandbox Code Playgroud)


Jör*_*tag 6

不,你不能在Ruby中做到这一点.在Ruby中,对象模型被烘焙到语言规范中,并且无法从程序中访问(当然也不可修改).即使在Rubinius中,这是一个主要用Ruby编写的Ruby实现,并且具有惊人的元编程功能,远远超出Ruby规范提供的功能,一些基本原语在C++中是硬连线的.

我并不是非常熟悉Python,但我很确定它也是一样的,即使在PyPy中也是如此.

可能能够做到,在Smalltalk中,通过修改(或子类)Behavior,它是超Class和定义的类和元类的行为.

当然可以在CLOS中执行此操作,或者更准确地说,使用CLOS的MOP(元对象协议).毕竟,这就是MOP的用途:定义对象模型.

与你所描述的最接近的OO概念似乎是Predicate Classes.谓词类是一个类,其实例不是静态定义的,而是由一组谓词定义的:满足谓词集的所有对象都是类的实例,只要谓词成立即可.在具有可变状态的语言中,这显然意味着对象可以随着状态的变化而"移入"谓词类中.它还意味着在任何给定时间,对象可以是许多谓词类的实例.

唯一的主流语言(对于"主流"的相当广泛的定义)我知道有谓词类是因子.

但请注意,即使在这里,也会定义谓词,并且对象既可以满足它们,也可以不满足.没有发现对象是否在运行时满足谓词的概念.

您可能也对Clojure关于临时分类的想法感兴趣.

最后,但同样重要的是,你可以看看Mikel Evins的名为Categories的对象系统.类别的最佳描述是按照时间顺序跟踪博客条目:

  1. 协议
  2. 分类
  3. 看一下分类
  4. 在罗马没有国王
  5. 向上弹出一个合理的传真
  6. 不同类别的类别
  7. 分类错误
  8. 在C3增值税的平的猫
  9. 分类0.2
  10. 诗人
  11. 巴德错综复杂

将来,大部分类别的开发将在Mikel的新语言Bard中完成,您可以按照Mikel新博客的Categories标签Bard标签来跟踪他们的进度.

然而,在一般情况下,我要说的是事实,知识管理和面向对象都使用这个词主要是一个历史悠久的事故.我不认为用另一个建模是很合适的.