У меня есть класс Book с переменной экземпляра title и методом title

class Book
  attr_accessor :title
  def title(title)
    @title = title.capitalize
  end
end

Я создаю объект книги

b = Book.new

И затем я установил заголовок

b.title("inferno")

Теперь, когда я пытаюсь распечатать значение переменной поля заголовка

p b.title

Руби думает, что я пытаюсь вызвать метод

"title": неправильное количество аргументов

Есть идеи, как распечатать значение переменной поля?

Спасибо

1
the_prole 27 Ноя 2016 в 00:49

3 ответа

Лучший ответ

Все, что делает attr_accessor :title, - это создает методы оболочки, идентичные def title() и def title=(value). Это просто генерация синтаксического метода сахара. Затем вы можете установить значение с помощью:

b.title = "Whatever"

И доступ с помощью:

b.title

Если вам просто нужен читатель или писатель, вы можете использовать attr_reader :title или attr_writer :title отдельно.

Если вы хотите создать свои собственные методы чтения / записи вручную, все, что описано выше, - это создать:

def title
  @title
end

def title=(value)
  @title = value
end

В Ruby не может быть двух методов с одинаковым именем и разной арностью, поэтому, когда вы определяете свой собственный метод (как в своем вопросе), вы перезаписываете метод чтения своим писателем. Это оставляет вам два способа установить и нет возможности читать.

Вы можете использовать attr_reader и собственный писатель:

def title=(value)
  @title = value.capitalize
end

Вы всегда можете назвать метод как угодно, например def capitalize_and_set_title(value). Это могло бы быть более очевидным, чем волшебство attr_accessor и перегрузки операторов.

5
Jim Stewart 26 Ноя 2016 в 21:58

Если вы хотите установить значение с помощью title(some_value) и прочитать его с помощью title (без аргументов), вы можете сделать, например:

class Book
  def title(title = :no_value_given)
    if title == :no_value_given
      @title
    else
      @title = title.capitalize
    end
  end
end

Это зависит от значения аргумента по умолчанию, когда вы вызываете его без аргументов.

Причина, по которой я не использовал nil в качестве значения аргумента по умолчанию, заключается в том, что вы можете установить значение nil.

0
Henrik N 26 Ноя 2016 в 23:03

Я думаю, что вы хотите установить заголовок:

def title=(str)
  super str.try(:capitalize)
end
0
David Aldridge 26 Ноя 2016 в 21:52