Отсутствует константа и "const_missing" внутри определения "class << self" - PullRequest
8 голосов
/ 14 марта 2011

Меня сильно смущает поведение Руби при определении const_missing и других методов класса внутри определения class << self в отличие от использования синтаксиса def self.foo.

Я пытался сделать что-то вроде этого:

class Foo
  class << self
    def foo
      puts MISSING
    end

    def const_missing(name)
      puts "#{name} missing"
    end
  end
end

Foo.foo

Я в основном использую синтаксис class << self для определения методов класса.Однако это не сработало, как ожидалось.const_missing никогда не называется.Вышеуказанное приводит к ошибке NameError.

Определение обоих методов выглядит следующим образом:

def self.foo
  puts MISSING
end

def self.const_missing(name)
  puts "#{name} missing"
end

Я подумал, что синтаксис class << self - это просто еще один способ определения методов класса, но полностьюэквивалентно def self.foo?Я проверял вышеупомянутое с MRI 1.8.7, 1.9.2 и JRuby 1.5.6.Очевидно, я что-то здесь упускаю?

Любой намек очень важен.

Спасибо, Мартин

1 Ответ

12 голосов
/ 14 марта 2011

class << self не является ярлыком для определения методов класса.Этот синтаксис (я не знаю точного именования) открывает собственный класс от объекта (в вашем случае, класса).При этом вы можете определить методы для объекта (не методы экземпляра).Но когда вы вызываете константу в собственном классе, вы вызываете константу из собственного класса, а не из класса.В этом случае вы должны определить метод класса на собственном классе для const_missing, два способа сделать это:

class Test
  class << self
    def foo
      p MISSING
    end

    # First way: (syntax sugar for the second way)
    def self.const_missing(name)
      name
    end

    # Second way:
    class << self # eigenclass of the eigenclass of the class
      def const_missing(name)
        name
      end
    end

  end
end

Test.foo #=> :MISSING
...