Ruby:将索引赋值重载到实例属性

时间:2011-03-04 18:21:11

标签: ruby operator-overloading

对于我正在编写的类的实例(ActiveRecord模型),我希望能够重载这样的赋值:

m.rank['foo'] = 1
m.rank['bar'] = 2

换句话说,我不希望将数字写入实际的@rank哈希值,而是希望使用'foo'和{{1}调用一些setter方法}作为参数。

获得此功能的一种天真方式是定义1set_rank(key, rank),但语法不是很含糖。为了更好的语法,可以定义一个定义get_rank(key)[]的辅助类,并让[]=方法返回该类的实例。

是否有一种既定的模式可以简洁地写出来?或者首先是一个坏主意,我应该使用rankset_rank

2 个答案:

答案 0 :(得分:4)

您可以通过初始化您的排名属性来实现此目的:

@rank = {}

def @rank.[] key
    puts "Retrieving key #{key}" #put code to execute when key is retrieved here
    begin
        self.fetch key
    rescue
        puts "Key not found" #put code to execute when key is not found here
        nil
    end
end

def @rank.[]= key, val
    puts "Setting key #{key} to #{val}" #put code to execute when key is set here
    self.store key, val
end

您需要在initialize方法中执行此操作,并使用attr_reader :rank(推荐)或attr_accessor :rank

<强>解释

这使用Ruby的一个叫做singleton方法的特性。使用单例方法可以在特定对象上定义方法,而不是在类的所有实例上定义方法。您可以在任何对象上定义单例方法。语法如上所述def identifier.method ... end

答案 1 :(得分:1)

我认为这很丑陋而且毫无用处。我的解决方案:

class Test
    attr_accessor :rank

    def initialize
        @rank = Rank.new
    end

    def meth(key, rank)
        print key, " ", rank
    end 

    class Rank
        def []=(key, rank)
            @test = Test.new
            @test.meth(key, rank)
        end
    end

end

m = Test.new
m.rank["key"] = "rank" # => key rank