代码之家  ›  专栏  ›  技术社区  ›  Bogdan Gusiev

具有来自includer类的静态方法调用的Ruby模块

  •  2
  • Bogdan Gusiev  · 技术社区  · 15 年前

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

    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
    

    还有其他方法来定义常数吗?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Simone Carletti    15 年前

    在你的具体情况下。

    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
    

    尽管有效,但还是有点乱。你确定你不能用不同的方式来实现你的目标吗?

        2
  •  2
  •   J.R. Garcia    13 年前

    在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
    

    您所做的(class<<base)实际上将您置于A的上下文中 metaclass ,而不是它本身。这个 find 方法在其自身上,而不是其元类上。要记住的是类本身就是对象,因此有自己的元类。

    为了让它更清楚:

    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
    

        3
  •  0
  •   Luke Woodward    12 年前
    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
    

    那么编译器错误已修复,请尝试。