2009-12-13 2 views
12

У меня есть класс с константой, определенной для него. Затем я определяю метод класса, который обращается к этой константе класса. Это прекрасно работает. Пример:(In 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 

Рубин интерпретирует метод как запрос константы из модуля, а не класс:

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

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

ответ

14

Это похоже на работу:

#! /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 

HTH

+0

Хорошо, это очищает вещи. Я еще не испытал синтаксис :: :). – jameshfisher

+0

Не прекращайте читать прямо сейчас. Читайте ниже ответ johannes. – Sebastian

9

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

+0

Спасибо! Это был тот метод, который я искал, но безуспешно. – jameshfisher

12

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

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

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

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

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

+0

Еще один полезный комментарий. Я узнал три вопроса, задав один вопрос. – jameshfisher