Ruby: перегрузка индексированного присваивания атрибутам экземпляра - PullRequest
3 голосов
/ 04 марта 2011

Для экземпляров класса, который я пишу (модель ActiveRecord), я бы хотел иметь возможность перегружать назначения следующим образом:

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

Другими словами, я не хочу, чтобы числа записывались в фактический хэш @rank, но я бы хотел, чтобы какой-то метод setter вызывался с 'foo' и 1 в качестве его параметров.

Наивным способом получить эту функциональность было бы определение set_rank(key, rank) и get_rank(key), но синтаксис не очень сладкий. Для лучшего синтаксиса можно определить вспомогательный класс, который определяет [] и []=, а метод rank возвращает экземпляр этого класса.

Существует ли установленный шаблон, чтобы написать это в сжатой форме? Или это плохая идея, и я должен просто использовать set_rank и get_rank?

Ответы [ 2 ]

4 голосов
/ 05 марта 2011

Вы можете добиться этого, инициализируя свой атрибут ранга следующим образом:

@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, называемая одноэлементными методами.Одиночные методы - это то, где вы определяете методы для определенных объектов, а не для всех экземпляров класса.Вы можете определить одноэлементные методы для любого объекта.Синтаксис, как указано выше, def identifier.method ... end.

1 голос
/ 04 марта 2011

Я думаю, что это довольно уродливо и совершенно бесполезно. Мое решение:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...