2016-09-21 3 views
2

Я использовал модуль для расширения функциональности класса. Но вдруг мне интересно, если это нормально, если я включать в себя модуль непосредственно в метод класса, а не в классе, как это:Включить модуль в метод ruby ​​

Оригинальное использование:

модель:

class Baby 
    include CommunicationSkills 

    def initialize(name) 
    @name = name 
    end 
end 

модуль:

module CommunicationSkills 
    def greet 
    "Hi" 
    end 
end 

так мы можем:

ivan = Baby.new('Iván') 
ivan.greet 
=> "Hi" 

но что, если я включаю метод внутри метода непосредственно:

class Baby 

    def initialize(name) 
    @name = name 
    end 

    def greet(language) 
    extend GreetLanguages 
    send(language) 
    end 
end 

модуль:

module GreetLanguages 
    def spanish 
    "Hola" 
    end 

    def english 
    "Hi" 
    end 
end 

так:

ivan = Baby.new('Iván') 
ivan.greet('spanish') 
=> "Hola" 
ivan.greet('english') 
=> "Hi" 

Я знаю, что это Возможное, но концептуально это правильно?

+0

Я не могу воспроизвести это. –

+0

Я получаю сообщение об ошибке в строке include: '> ivan.greet ('spanish') NoMethodError: undefined method' include 'for # ' – Ryan

+0

Да, относительно @ davidhu2000 Я обновил код. Прости. –

ответ

0

Модуль содержит два метода экземпляра. Вы хотите отправить их в экземпляр, а не в класс, поэтому вам нужен include модуль (с использованием Module#include), а не extend. Для вызова include из метода экземпляра (self, являющегося экземпляром), вы должны отправить include в self.class. Поэтому вам необходимо написать следующее.

class Baby 
    def initialize(name) 
    @name = name 
    end 
    def greet(language) 
    self.class.include GreetLanguages 
    send(language) 
    end 
end 

ivan = Baby.new('Iván') 
ivan.greet('spanish') 
    #=> "Hola" 

Baby.instance_methods.include?(:english) && Baby.instance_methods.include?(:spanish) 
    #=> true 

ivan.greet('english') 
    #=> "Hi" 

Вы также можете написать ivan.greet(:spanish).

Вы должны использовать Object#extend, если вы хотите преобразовать методы экземпляра в модуле в методы класса, когда вы вводите их в класс.

class Baby 
    def initialize(name) 
    @name = name 
    end 
    def extend_mod 
    self.class.extend GreetLanguages 
    end 
end 

Baby.new('Iván').extend_mod 
Baby.methods.include?(:spanish) && Baby.methods.include?(:english) #=> true 

Baby.spanish 
    #=> "Hola" 
Baby.english 
    #=> "Hi" 

Это необычно для вызова include или extend изнутри метода экземпляра. Я не знаю, зачем это нужно.

0
module GreetLanguages 
    def spanish 
    "Hola" 
    end 

    def english 
    "Hi" 
    end 
end 

class Baby 

    def initialize(name) 
    @name = name 
    end 

    def greet(language) 
    extend GreetLanguages 
    send(language) 
    end 
end 

Таким образом, мне удалось получить этот код работает, используя extend. Кроме того, в вашей функции send вам нужно удалить кавычки, потому что вы не отправляете строку "language", вы отправляете язык переменных, которые представляют строку "spanish" или "english".

Таким образом, у include нет прямого приемника, поэтому он в основном звонит по телефону self. Когда вы используете include в методе экземпляра для класса Baby, вы добавляете модуль к экземпляру ivan, что не имеет никакого смысла.

extend добавляет модуль как методы класса, поэтому сам экземпляр может вызвать метод. Итак, мы добавляем модуль к экземпляру ivan, и теперь, когда мы можем позвонить greet.

Я действительно не вижу причин для этого, лучше всего использовать include на уровне класса.

+0

Метод 'greet' вызывает ошибку в экземпляре' Baby'. –

+0

Какая ошибка? И покажите мне свой код – davidhu2000

+0

Я вызываю 'greet (spanish)' и ошибка, которую я получаю, это: 'undefined local variable или method' spanish 'для main: Object (NameError) '. –

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