ruby运算符重载问题

12 ruby overloading operator-overloading operators

为了娱乐目的,我一直在玩ruby和opengl,我决定写一些3d矢量/平面/等级类来完成一些数学运算.

简化示例:

class Vec3
    attr_accessor :x,:y,:z

    def *(a)
        if a.is_a?(Numeric) #multiply by scalar
            return Vec3.new(@x*a, @y*a, @z*a)
        elsif a.is_a?(Vec3) #dot product
            return @x*a.x + @y*a.y + @z*a.z
        end
    end
end

v1 = Vec3.new(1,1,1)
v2 = v1*5 #produces [5,5,5]
Run Code Online (Sandbox Code Playgroud)

一切都很好,花花公子,但我也想写

v2 = 5*v1
Run Code Online (Sandbox Code Playgroud)

这需要为Fixnum或Float或其他任何东西添加功能,但我找不到重载或扩展fixnum的乘法而不完全替换它的方法.红宝石有可能吗?有小费吗?

(显然,如果需要,我可以按正确的顺序写下我的所有乘法)

hor*_*guy 22

使用coerce是一种比猴子修补核心类更好的方法:

class Vec3
    attr_accessor :x,:y,:z

    def *(a)
        if a.is_a?(Numeric) #multiply by scalar
            return Vec3.new(@x*a, @y*a, @z*a)
        elsif a.is_a?(Vec3) #dot product
            return @x*a.x + @y*a.y + @z*a.z
        end
    end

    def coerce(other)
        return self, other
    end
end
Run Code Online (Sandbox Code Playgroud)

如果您将v定义为,v = Vec3.new那么以下将起作用:v * 5并且5 * v coerce(self)返回的第一个元素成为操作的新接收器,第二个元素(other)成为参数,因此5 * v完全等效于v * 5

  • 强制+1。代表必须调试您的代码的人,请不要对核心类进行猴子补丁,除非绝对必要。 (2认同)