Ruby:重载实例属性的索引分配

发布于 2024-10-20 02:52:22 字数 506 浏览 0 评论 0原文

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

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

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

获得此功能的一个简单方法是定义 set_rank(key,rank)get_rank(key),但语法不是很甜。为了获得更好的语法,可以定义一个辅助类来定义 [][]=,并让 rank 方法返回该类的实例班级。

是否有既定的模式可以简洁地编写此内容?或者这从一开始就是一个坏主意,我应该只使用 set_rankget_rank

For the instances of a class that I'm writing (an ActiveRecord model), I'd like to be able to overload assignments like this:

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

In other words, I don't want the numbers to be written into an actual @rank hash, but rather I'd like to have some setter method called with 'foo' and 1 as its parameters.

A naive way to get this functionality would be to define set_rank(key, rank) and get_rank(key), but the syntax isn't very sugary. For nicer syntax, one could define a helper class that defines [] and []=, and have the rank method return an instance of that class.

Is there an established pattern to write this in a concise manner? Or is it a bad idea in the first place, and I should just use set_rank and get_rank?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

许你一世情深 2024-10-27 02:52:22

您可以通过初始化您的排名属性来实现此目的,如下所示:

@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 :排名。

说明

这使用了 Ruby 中称为单例方法的功能。单例方法是在特定对象而不是类的所有实例上定义方法的地方。您可以在任何对象上定义单例方法。语法如上所示,defidentifier.method ... end

You can achieve this by initialising your rank attribute like so:

@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

You will need to do this in your initialize method and use attr_reader :rank (recommended) or attr_accessor :rank.

Explanation

This uses a feature of Ruby called singleton methods. Singleton methods are where you define methods on specific objects rather than on all instances of a class. You can define singleton methods on any object. The syntax is, as above, def identifier.method ... end.

孤城病女 2024-10-27 02:52:22

我认为它非常丑陋而且完全没用。我的解决方案:

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

I think it's pretty ugly and totally useless. My solution:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文