2013-09-04 5 views
1

В настоящее время мы пытаемся изучить учебник rspec и будем очень благодарны за некоторые разъяснения.Ruby: Методы и инициализация классов

Кодекс:

class Book 

    attr_reader :title 

    def initialize(title=nil) 
     @title = title = title && title.capitalize! 
    end 

    def title=(new_title = nil) 
     @title = new_title && new_title.each do |word| 
     word.capitalize! 
    end 
end 

Два вопроса:

  1. Почему существуют два набора @title (то есть: почему это определено в обоих initialize и title как набор = к различным вещи)?

  2. Почему метод title имеет после него =? Код ломается, если я не использую =.

редактировать: для целей моего RSpec учебник это код, я наконец-то попробовал, что работал

class Book 
    attr_accessor :title 

    def initialize(title = nil) 
     @title = title 
    end 

    def title=(book_title = nil) 
     @title = book_title.capitalize 
    end 
end 

Моя первая проблема была с заглавной = метод. Наконец, я наткнулся на поток, который объясняет, что такое функция method =. Это необходимо, если вы хотите присвоить значение чему-то в методе класса (по крайней мере, это мое понимание на данный момент. Не стесняйтесь исправлять меня).

Буду признателен за любые советы в этом новом коде.

ответ

1

Давайте анализируем, что:

attr_reader :title 

Здесь мы в основном определении метода:

def title; @title; end 

который возвращает экземпляр переменной @title.

def initialize(title=nil) 
    @title = title = title && title.capitalize! 
end 

Здесь мы определяем аргументы конструктора 0-1, который может быть уменьшен до:

def initialize(title=nil) 
    title && @title = title.capitalize 
end 

Дело в том, что title внутри конструктора является переменной аргумент, а не title или title= метод, поэтому метод title=, определенный ниже, здесь никогда не вызывается. Обратите внимание, что здесь && используется для short-circuit evaluation.

def title=(new_title = nil) 
    @title = new_title && new_title.each do |word| 
    word.capitalize! 
end 

Здесь мы на самом деле есть две синтаксических ошибок: первая является то, что для String с (который я предполагаю, является типом названия, как представляется, вызвать String#capitalize! позже) не имеет методы each. Тот, кто написал это, вероятно, имел в виду String#each_char или String#split он сначала вместо этого.

Вторая ошибка заключается в том, что блок после each не закрыт end.

Теперь предполагая эту версию вместо того, чтобы:

def title=(new_title = nil) 
    @title = new_title && new_title.split(' ').each { |word| word.capitalize! }.join(' ') 
end 

title= бы просто присвоить title к @title переменной по той же причине (оценка короткого замыкания), как и раньше, и может быть уменьшено до:

def title=(new_title = nil) 
    new_title && @title = new_title 
end 
+0

Очень полезно (мне нужно будет его прочитать несколько раз, но он уже начинает помогать мне понять). Уточнение: обе ошибки, которые вы указали, были мной, написав следующую часть кода. Я забыл изменить его в своем первоначальном формате, прежде чем опубликовать (извините! И спасибо за исправление: D). –

+0

Мой код больше не работает. Когда я удалил оценки короткого замыкания, как в ваших примерах, он полностью сломался. мой код класс 'Book' ' attr_reader: title' определение функции инициализации (название = ноль) '' @title = title.capitalize' 'end' ' название DEF = (NEW_TITLE = ноль) ' ' @title = new_title' 'end' ' end' Я также пробовал его с помощью 'new_title.split ('') .each do | word | word.capitalize конец ' а также 'new_title.each_char do | word | word.capitalize end ' –

+0

Я не думаю, что вы можете сократить код так, как у вас есть. Переход от '@title = title = title && title.capitalize!' К '@title = title.capitalize' теперь генерирует исключение, если' title' равно нулю. Для метода 'title =' удаление части капитализации означает, что 'new_title' не получает заглавные буквы. Кроме того, вам нужно «присоединить» строку разделения (иначе @title станет массивом вместо строки). –

0

Метод initialize вызывается при построении экземпляра класса. Значение @title = ... устанавливает начальное значение @title.

Метод title= вызывается, когда кто-то впоследствии устанавливает значение заголовка в экземпляре класса. Затем он корректирует значение @title соответственно. См. Ruby Accessors для подробного объяснения.

В качестве примера:

book = Book.new  # calls initialize 
book.title = 'foo' # calls title= 
+0

так что 'title =' - это просто метод, который вызывает другую версию @title (которую затем можно манипулировать, чтобы делать все, что вы хотите) –

+0

Это не другая версия метода, это совсем другое. у. title = - метод, @title - переменная экземпляра. –

+0

Ahhh ок. Это имеет больший смысл. Еще одна вещь: @ Джефффри говорил, что я могу сократить свой код. Но теперь он ломается, когда я не использую разделы '&&'. Есть ли способ сократить его или я должен держать '&&' s в –

Смежные вопросы