红宝石运算符重载问题 [英] ruby operator overloading question

查看:69
本文介绍了红宝石运算符重载问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于娱乐目的,我一直在使用ruby和opengl,我决定编写一些3d vector/plane/etc类来完善一些数学.

i've been messing around with ruby and opengl for entertainment purposes, and i decided to write some 3d vector/plane/etc classes to pretty up some of the math.

简化示例:

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]

一切都很好,但我也想写

which all fine and dandy, but i also want to be able to write

v2 = 5*v1

这需要向Fixnum或Float或其他功能添加功能,但是我无法找到一种方法来重载或扩展fixnum的乘法而不完全替换它.这在红宝石中可能吗?有什么提示吗?

which requires adding functionality to Fixnum or Float or whatever, but i couldn't find a way to overload or extend fixnum's multiplication without replacing it entirely. is this possible in ruby? any tips?

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

(obviously i can just write all my multiplications in the correct order if i need to)

推荐答案

使用强制性方法比用猴子修补核心类要好得多:

Using coerce is a MUCH better approach than monkey-patching a core class:

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

如果将v定义为v = Vec3.new,则以下内容将起作用:v * 55 * v 由coerce(自身)返回的第一个元素成为该操作的新接收者,而第二个元素(其他)则成为该参数,因此5 * v完全等同于v * 5

if you define v as v = Vec3.new then the following will work: v * 5 and 5 * v The first element returned by coerce (self) becomes the new receiver for the operation, and the second element (other) becomes the parameter, so 5 * v is exactly equivalent to v * 5

这篇关于红宝石运算符重载问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆