9

第一次在堆栈溢出。

我正在研究使用 Ruby 或 Python 提供的一些元编程特性,但首先我需要知道它们允许我扩展语言的程度。我需要做的主要事情是重写Class的概念。这并不意味着我想在运行时重写一个特定的类,而是我想对什么是进行自己的概念化。在这里更具体一点,我想做一些人们通常所说的类的东西,但我想遵循一个“开放的世界”” 假设。在普通类的“封闭世界”中,如果我将 Poodle 声明为 Dog 的子类为 Animal 的子类,那么我知道 Poodle 不会也是 FurCoat 的一种。但是,在打开世界类,然后我定义的贵宾犬对象可能是也可能不是 FurCoat 类型的对象,直到我解释说我可以穿贵宾犬,我们才能确定。(可怜的贵宾犬。)这一切都必须做我正在进行一项关于 OWL 本体的研究。

正如你所知,我试图在网上查找信息,但由于这里的术语过多,我没有发现任何有用的信息。

非常感谢,约翰

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

4

5 回答 5

8

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

try:
    poodle.wear()
except (AttributeError, TypeError):
    pass
于 2010-05-23T00:16:21.780 回答
7

I agree with Samir that it just sounds like duck typing. You don't need to care what 'type' an object really 'is' you only need bother with what an object can 'do'. This is true in both Ruby and Python.

However if you really are checking the types of classes and you really do need to have a Poodle object optionally also be a FurCoat at runtime, then the way to do this in Ruby is to mixin a FurCoat module into the Poodle object, as follows:

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

EDIT (due to your updated question):

You still do not need to rewrite Class to achieve what you want, you just need to monkey-patch the kind_of? and is_a? (and potentially instance_of?) methods on Ruby's Kernel module. Since Ruby has open classes this is easily done:

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

And then define for each class (or module) what it means for an object to implement its 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

Now test it:

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
于 2010-05-23T00:42:03.833 回答
6

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

我对Python不是很熟悉,但我很确定它是一样的,即使在PyPy中也是如此。

可以Smalltalk中通过修改(或子类化)class来做到这一点,Behaviorclass是类和元类的超类Class并定义了类和元类的行为。

当然可以在CLOS中做到这一点,或者更准确地说是使用CLOS 的 MOP元对象协议)。毕竟,这就是 MOP 的用途:定义对象模型。

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

我所知道的唯一具有谓词类的主流语言(对于“主流”的相当广泛的定义)是Factor

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

您可能还对Clojuread-hoc 分类法的想法感兴趣。

最后但同样重要的是,您可以看看Mikel Evins的名为Categories的对象系统。类别的最佳描述是按时间顺序简单地跟随博客条目:

  1. 协议
  2. 类别
  3. 类别一览
  4. 罗马没有国王
  5. 弹出一个合理的传真
  6. 不同类别的类别
  7. 类别错误
  8. C3 桶中的扁平猫
  9. 类别 0.2
  10. 诗人
  11. 吟游诗人错综复杂

未来,Category 的大部分开发都将使用 Mikel 的新语言Bard完成,您可以通过关注Mikel 新博客的 Categories 标签Bard 标签来跟踪他们的进展。

然而,总的来说,我会说知识管理和面向对象都使用这个词的事实主要是一个历史性的意外。我不认为一个与另一个建模是一个很好的选择。

于 2010-05-23T05:59:52.677 回答
2

在 Python 中,您可以在运行时更改类的继承,但在每个给定时间,除非另有声明,否则类不是另一个类的子类。没有“可能或不可能”——这需要 Python 不支持的三元逻辑。当然,您可以编写自己的“Is-a”和“Has-a”函数来将 OWL 本体映射到 Python 类。

于 2010-05-23T00:26:54.573 回答
1

我认为,在使用开放词假设表示信息时,无论多么动态,依赖类结构都是一种倒退。

用作模板的类和用作实例的对象在与 OWA 一起使用时绝对没有任何优势。考虑一个 Person 类,我们在其中编码一个人有 2 条腿的知识。但是,我们不能推断 Person 的实例将有两条腿,因为该人可能有残疾。

如果类属性在上面的例子中没有任何意义,那么使用它们或任何其他层次结构来编码信息似乎没有什么意义。

于 2010-05-23T03:26:30.690 回答