(在Ruby中)允许混合类方法访问类常量

jam*_*her 12 ruby module class constants class-method

我有一个定义了常量的类.然后我定义了一个访问该类常量的类方法.这很好用.一个例子:

#! /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
Run Code Online (Sandbox Code Playgroud)

我的问题出现在尝试将此类方法移出到外部模块,如下所示:

#! /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
Run Code Online (Sandbox Code Playgroud)

Ruby将方法解释为从模块而不是类中请求常量:

line 5:in `shout_my_constant': uninitialized constant CommonMethods::Const (NameError)
Run Code Online (Sandbox Code Playgroud)

那么,你的伙伴们有什么神奇的技巧让方法访问类不变?非常感谢.

Aid*_*lly 16

这似乎有效:

#! /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
Run Code Online (Sandbox Code Playgroud)

HTH


小智 13

可能值得注意的是,您不需要将模块包含到元类中.

class NonInstantiableClass
    Const = "hello, world!"
    class << self
        include CommonMethods
    end
end
Run Code Online (Sandbox Code Playgroud)

Ruby有一个extend关键字,可以有效地将模块接口添加到类中,例如

class NonInstantiableClass
    Const = "hello, world!"
    extend CommonMethods
end
Run Code Online (Sandbox Code Playgroud)

您仍然需要确保使用self::Const或引用正确的常量const_get,但这extend <module>是将这些方法添加到类中的更好方法.


joh*_*nes 9

问题是,如果您只是编写Const,则会在模块创建时评估它.你必须这样使用Module#const_get:const_get(:Const).执行该方法时,将在运行时对此进行评估.所以这发生在你的班级而不是你的模块中.