2015-06-20 4 views
1

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

module Pet 
    def initialize name, is_pet 
    @is_pet = is_pet 
    if is_pet 
     @name = name 
    else 
     @name = "Unnamed" 
    end 
    end 
    def pet? 
    return @is_pet 
    end 
    def get_name 
    return @name 
    end 
end 

class Dog 
    include Pet 
    def initialize tricks, name, is_pet 
    @tricks = tricks 
    super name, is_pet 
    end 
    def get_tricks 
    return @tricks 
    end 
end 

Вот что я могу делать с ним:

d = Dog.new ["roll", "speak", "play dead"], "Spots", true 

d.pet?  #=> true 
d.get_tricks #=> ["roll", "speak", "play dead"] 
d.get_name #=> "Spots" 

Он отлично работает, но я просто интересно, если есть лучший способ сделай это.

ответ

1
  • Это не является хорошей практикой программирования на жесткий код фиксированной строки, как "Unnamed" в качестве значения для @name. В таком случае вы должны назначить nil и выполнять любую модификацию при печати. Предположим, вы это сделали.

  • Тогда is_pet можно вывести из того name является nil или нет, поэтому он является излишним иметь, что в качестве переменной экземпляра. Вы можете просто применить !! к name, чтобы получить is_pet. Поэтому вам следует избавиться от такой переменной экземпляра.

  • У вас есть get_ префиксы как методы getter, но в Ruby лучше использовать то же имя, что и переменные экземпляра (без атак) в качестве имени получателя.

Это даст вам:

module Pet 
    attr_reader :name 
    def initialize name; @name = name end 
end 

class Dog 
    include Pet 
    attr_reader :tricks 
    def initialize tricks, name 
    @tricks = tricks 
    super(name) 
    end 
end 

d = Dog.new ["roll", "speak", "play dead"], "Spots" 
d.tricks #=> ["roll", "speak", "play dead"] 
d.name #=> "Spots" 
!!d.name #=> true (= `is_pet`) 
+0

Спасибо, очень полезно – hexagonest

0

Не писать код, который вызывает super попасть в включаемого модуля. Не пишите модули, которые ожидают, что дети вызовут супер. Дело не в модулях.

Это хороший объектно-ориентированный стиль, чтобы не спрашивать о каких вещах. Посмотрите «скажите, не спрашивайте» и «утка» набираете в общем.

Если вы хотите предоставить метод initialize по умолчанию, вы, возможно, возможно хотите наследование. Но иногда существуют допустимые варианты использования для переопределения инициализации в модуле. Идиоматической задачей здесь является метод крюка:

module Pet 
    def initialize(options = {}) 
    @name = options[:name] 
    post_initialize(options) 
    end 

    def post_initialize(options = {}) 
    # can be overridden in including modules 
    end 
end 

class Dog 
    include Pet 

    def post_initialize(options = {}) 
    @tricks = options[:tricks] 
    end 
end 

dog = Dog.new(name: "Fido", tricks: ["play dead", "roll over"]) 

Модуль предназначен для включения некоторого совместного поведения между различными вещами. Хорошо рассматривать это как прилагательное, описывающее, что вы можете сделать с классом, который включает его. Слова, заканчивающиеся на «-able» (например, Enumerable или Comparable), описывающие класс-получатель, или «-or» (Iterator, Interactor), описывающие класс выполнения, являются хорошими кандидатами для модулей.

+0

Причина, по которой я использую модуль для этого, состоит в том, что у меня есть несколько классов, наследуемых от класса «Млекопитающее». Собака наследует от «Млекопитающего», поэтому я не могу унаследовать от Pet. Кроме того, домашнее животное является скорее одеялом и меньше объектом, и я думал, что это то, что сделали модули. – hexagonest

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