对于我正在编写的类的实例(ActiveRecord模型),我希望能够重载这样的赋值:
m.rank['foo'] = 1
m.rank['bar'] = 2
换句话说,我不希望将数字写入实际的@rank
哈希值,而是希望使用'foo'
和{{1}调用一些setter方法}作为参数。
获得此功能的一种天真方式是定义1
和set_rank(key, rank)
,但语法不是很含糖。为了更好的语法,可以定义一个定义get_rank(key)
和[]
的辅助类,并让[]=
方法返回该类的实例。
是否有一种既定的模式可以简洁地写出来?或者首先是一个坏主意,我应该使用rank
和set_rank
?
答案 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