Подтвердить что ты не робот

(В Ruby), позволяющий методам смешанного класса получить доступ к константам класса

У меня есть класс с константой, определенной для него. Затем я определяю метод класса, который обращается к этой константе класса. Это прекрасно работает. Пример:

#! /usr/bin/env ruby

class NonInstantiableClass
    Const = "hello, world!"
    class << self
        def shout_my_constant
            puts Const.upcase
            end
        end
    end

NonInstantiableClass.shout_my_constant

Моя проблема возникает при попытке переместить этот метод класса во внешний модуль, например:

#! /usr/bin/env ruby

module CommonMethods
    def shout_my_constant
        puts Const.upcase
        end
    end

class NonInstantiableClass
    Const = "hello, world!"
    class << self
        include CommonMethods
        end
    end

NonInstantiableClass.shout_my_constant

Ruby интерпретирует метод как запрашивающий константу из модуля, а не класс:

line 5:in `shout_my_constant': uninitialized constant CommonMethods::Const (NameError)

Итак, какие волшебные трюки вам нравятся, чтобы позволить методу получить доступ к константе класса? Большое спасибо.

4b9b3361

Ответ 1

Это работает:

#! /usr/bin/env ruby

module CommonMethods
    def shout_my_constant
        puts self::Const.upcase
    end
end

class NonInstantiableClass
    Const = "hello, world!"
    class << self
        include CommonMethods
    end
end

NonInstantiableClass.shout_my_constant

НТН

Ответ 2

Вероятно, стоит отметить, что вам не нужно включать модули в метакласс.

class NonInstantiableClass
    Const = "hello, world!"
    class << self
        include CommonMethods
    end
end

Ruby имеет ключевое слово extend, которое эффективно добавляет интерфейс модулей к классу, например.

class NonInstantiableClass
    Const = "hello, world!"
    extend CommonMethods
end

Вам все равно нужно убедиться, что вы ссылаетесь на правую константу, используя self::Const или const_get, но extend <module> - лучший способ добавить эти методы в класс.

Ответ 3

Проблема заключается в том, что если вы просто пишете Const, ее оценивают по времени создания модуля. Вы должны использовать Module#const_get вместо этого следующим образом: const_get(:Const). Это оценивается во время выполнения, когда метод выполняется. Так что это происходит в вашем классе, а не в вашем модуле.