【问题标题】:Copy/Inheritance of Ruby Matrix class (core/std lib)Ruby Matrix 类的复制/继承(核心/标准库)
【发布时间】:2011-05-19 21:07:46
【问题描述】:

我尝试在 Ruby 中扩展现有的 Singleton 类,例如 Matrix 类。

我的第一个 quick&dirty 解决方案是猴子补丁(重新打开类并扩展功能)。

但我认为,猴子补丁一般都不好,特别是如果有人试图覆盖核心类的基本方法,如字符串、整数等......

下一步是找出如何获得具有新名称(如 MatrixExt)的 Matrix 类的真实硬拷贝,该名称表现为独立的单例。

MatrixExt = Matrix

没有完成这项工作,因为它导致:

MatrixExt.scalar(2,0)
=> Matrix[[0, 0], [0, 0]]

所以我只能为同一个单例获得多个名称。不,我想要的。

clone 和 dup 方法的结果相同。

类继承也不起作用:

class MatrixExt < Matrix
  # patches ...
end

MatrixExt.scalar(2,0)
=> Matrix[[0, 0], [0, 0]]

这是最令人困惑的部分,因为在自定义类中可能会获得继承类。 (那么,为什么 core/std lib 类的工作方式不同?)

我目前的解决方案是有一个带有扩展名的模块,然后在初始化后显式使用.extend,例如:

m = Matrix.scalar(2,0).extend(MatrixExtModule)

暂时没关系,但我的问题是:

还有其他解决方案吗?如果有,该怎么做?

(不,复制matrix.rb当然不是好办法。;o)

我做错了什么或我的想法有问题?

在此先感谢您提供任何解决方案和/或启发灵感!

【问题讨论】:

    标签: ruby inheritance matrix singleton


    【解决方案1】:

    这是一个错误。

    我创建了一个issue on redmine.ruby-lang.org,这是修复这些问题的建议。

    我修复了库,但恐怕要到 Ruby 1.9.4 才能使用它。

    【讨论】:

    • 我认为这是一种有意的行为。 ;o)
    【解决方案2】:

    如果您查看Matrix 是如何实现的,您会注意到scalar、diagonal 等所有方法都调用了私有new 方法,该方法将始终返回一个新的Matrix 对象(你不重写方法,所以 Ruby 会去看看超类的实现,new 的隐式接收者是self,即Matrix 类)。

    我猜你最好的办法是把你所有的补丁包在一个模块中,然后用猴子补丁 Matrix 这样。

    【讨论】:

    • 你的意思是像:class Matrix; extend MatrixExt; end
    • (平均:... include MatrixExt ...)
    • 如果你做了class MyObject; end; MyObject.new,你最终会得到一个类为MyObject而不是Object的对象,即使你还没有实现MyObject.new。怎么不一样?
    • 如果您查看Class#new 的C 源代码,您将看到obj = rb_obj_alloc(klass);,这意味着在initialize 被rb_obj_call_init(obj, argc, argv); 调用之前,将使用当前类创建返回的对象。在Matrix 示例中,new 是一个私有方法,不能使用显式接收器调用,因此当diagonal 等其他方法调用它时,self 将始终为Matrix。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多