Ruby模块,使用来自includer类的静态方法调用

时间:2023-01-15 18:55:56

I need to define the constant in the module that use the method from the class that includes this module:

我需要在模块中定义使用包含此模块的类中的方法的常量:

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

But the compiler gives the error on the 4th line.

但是编译器在第4行给出了错误。

Is there any other way to define the constant?

有没有其他方法来定义常量?

3 个解决方案

#1


The more idiomatic way to achieve this in Ruby is:

在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

What you were doing (class << base) actually puts you into the context of A's metaclass, not A itself. The find method is on A itself, not its metaclass. The thing to keep in mind is that classes are themselves objects, and so have their own metaclasses.

你正在做什么(类<< base)实际上会让你进入A的元类的上下文,而不是A本身。 find方法在A本身,而不是它的元类。要记住的是,类本身就是对象,因此有自己的元类。

To try to make it clearer:

试图让它更清晰:

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

Not sure if that helps, but if you don't understand it, you can still use the class_eval idiom above.

不确定这是否有帮助,但如果你不理解它,你仍然可以使用上面的class_eval习语。

#2


In your specific case.

在你的具体情况下。

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

Despite it works, it's a little bit messy. Are you sure you can't follow a different way to achieve your goal?

尽管它有效,但它有点乱。您确定不能以不同的方式实现目标吗?

#3


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

then the compiler error is fixed, pls try.

那么编译错误是固定的,请试试。

#1


The more idiomatic way to achieve this in Ruby is:

在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

What you were doing (class << base) actually puts you into the context of A's metaclass, not A itself. The find method is on A itself, not its metaclass. The thing to keep in mind is that classes are themselves objects, and so have their own metaclasses.

你正在做什么(类<< base)实际上会让你进入A的元类的上下文,而不是A本身。 find方法在A本身,而不是它的元类。要记住的是,类本身就是对象,因此有自己的元类。

To try to make it clearer:

试图让它更清晰:

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

Not sure if that helps, but if you don't understand it, you can still use the class_eval idiom above.

不确定这是否有帮助,但如果你不理解它,你仍然可以使用上面的class_eval习语。

#2


In your specific case.

在你的具体情况下。

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

Despite it works, it's a little bit messy. Are you sure you can't follow a different way to achieve your goal?

尽管它有效,但它有点乱。您确定不能以不同的方式实现目标吗?

#3


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

then the compiler error is fixed, pls try.

那么编译错误是固定的,请试试。