Есть ли способ заставить attr_reader создавать методы с другим именем, чем переменная экземпляра? - PullRequest
1 голос
/ 24 апреля 2011

В Ruby есть способ сделать что-то вроде

class Foo
    attr_reader :var_name :reader_name #This won't work, of course
    def initialize
        @var_name = 0
    end
end

# stuff here ....

def my_method
    foo = Foo.new
    assert_equal 0,foo.reader_name
end

Другими словами, существует ли стандартный способ создания метода доступа для переменной, которая использует имя, отличное от переменной. (Помимо ручного кодирования, конечно.)

Ответы [ 3 ]

4 голосов
/ 24 апреля 2011

Невозможно передать какие-либо параметры attr_reader

Это кодировка?

class Foo
  def initialize
      @var_name = 0
  end
  def reader_name; @var_name; end
end
3 голосов
/ 24 апреля 2011

Вы можете использовать alias_method:

class Foo
    attr_reader :var_name
    alias_method :reader_name, :var_name
    def initialize
        @var_name = 0
    end
end

Метод var_name, созданный attr_reader, все еще будет доступен. Вы можете использовать remove_method, чтобы избавиться от метода var_name, если вы действительно этого хотите (но убедитесь, что вы получаете все в правильном порядке):

class Foo
    attr_reader :var_name
    alias_method :reader_name, :var_name
    remove_method :var_name
    def initialize
        @var_name = 0
    end
end

Если бы вы действительно хотели, вы могли бы обезопасить патч attr_reader_as метода в Module:

class Module
    def attr_reader_as(attr_name, alias_name)
        attr_reader attr_name
        alias_method alias_name, attr_name
        remove_method attr_name
    end
end

class Foo
    attr_reader_as :var_name, :reader_name
    def initialize
        @var_name = 0
    end
end

Лучше attr_reader_as будет принимать хеш (например, {:var_name => :reader_name, :var_name2 => :reader_name2}), но я оставлю это в качестве упражнения для читателя.

2 голосов
/ 25 апреля 2011

Прежде всего, моя мантра: Хороший программист хорошо играет своих товарищей по команде.Следование соглашениям - это хорошая игра для других.

То, что вы хотите, кажется нетрадиционным, и, как утверждает @edgerunner, это плохая практика (читай: я бы вас ударил).Все, что я говорю, подумай дважды об этом, я не знаю твоего сценария использования, он может оказаться верным ... В любом случае, на Пасху должно быть позволено немного повеселиться, поэтому я попрактиковался в метапрограммировании и поиграл с Миксинами.

class Foo
  include MyAttrReader
  my_attr_reader :var_name, :reader_name
  def initialize
    @var_name = 0
  end
end

довольно чисто.Модуль делает свое дело (обязательно загрузите этот модуль перед уроком)

module MyAttrReader
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def my_attr_reader(attribute, read_attribute)
      define_method "#{read_attribute}" do
        instance_variable_get "@#{attribute}"
      end
    end
  end
end

Тестирование в irb

ruby-1.9.2-p180 :001 > load 'my_attr_reader.rb'
 => true 
ruby-1.9.2-p180 :002 > load 'foo.rb'
 => true 
ruby-1.9.2-p180 :003 > f = Foo.new
 => #<Foo:0x00000100979658 @var_name=0> 
ruby-1.9.2-p180 :004 > f.reader_name
 => 0 
ruby-1.9.2-p180 :005 > f.var_name
NoMethodError: undefined method `var_name' for #<Foo:0x00000100979658 @var_name=0>

Я надеюсь, вы понимаете, насколько это будет не интуитивно понятно для других.Вы можете переопределить метод to_s, чтобы показать, как получить доступ к @var_name, но я бы не пошел туда ... или тоже определил метод var_name (два метода getter).Придерживайтесь соглашений.Во всяком случае, мне было очень весело, удачи!

...