Модуль Ruby со статическим вызовом метода из класса includeder - PullRequest
2 голосов
/ 26 июня 2009

Мне нужно определить константу в модуле, который использует метод из класса, который включает этот модуль:

module B 
  def self.included(base)
    class << base
  CONST = self.find
    end
  end
end 

class A
  def self.find
    "AAA"
  end
  include B 
end

puts A::CONST

Но компилятор выдает ошибку в 4-й строке.

Есть ли другой способ определить константу?

Ответы [ 3 ]

2 голосов
/ 30 июня 2009

Более идиоматический способ добиться этого в Ruby:

module B 
  def self.included(klass)
    klass.class_eval <<-ruby_eval
      CONST = find
    ruby_eval

    # note that the block form of class_eval won't work
    # because you can't assign a constant inside a method
  end
end

class A
  def self.find
    "AAA"
  end
  include B 
end

puts A::CONST

То, что вы делали (класс << base), фактически помещает вас в контекст <code>metaclass А, а не самого А. Метод find находится на самом A, а не на его метаклассе. Следует помнить, что сами классы являются объектами и поэтому имеют свои собственные метаклассы.

Чтобы попытаться прояснить ситуацию:

class Human
  def parent
    # this method is on the Human class and available
    # to all instances of Human.
  end

  class << self
    def build
      # this method is on the Human metaclass, and
      # available to its instance, Human itself.
    end

    # the "self" here is Human's metaclass, so build
    # cannot be called.
  end

  def self.build
    # exactly the same as the above
  end

  build # the "self" here is Human itself, so build can
        # be called
end

Не уверен, поможет ли это, но если вы этого не понимаете, вы все равно можете использовать идиому class_eval выше.

2 голосов
/ 26 июня 2009

В вашем конкретном случае.

module B 
  def self.included(base)
    base.const_set("CONST", base.find)
  end
end 

class A
  def self.find
    "AAA"
  end
  include B 
end

puts A::CONST

Несмотря на то, что это работает, это немного грязно. Вы уверены, что не можете пойти другим путем для достижения своей цели?

0 голосов
/ 19 октября 2010
module B 
  def self.included(base)
    class << base
      CONST = self.find
    end
  end
end 

class A
  class << self
    def self.find
       "AAA"
    end
  end
  include B 
end

тогда ошибка компилятора исправлена, пожалуйста попробуйте.

...