Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Ruby中,可以从超类定义子类中的常量吗?_Ruby_Class_Constants - Fatal编程技术网

在Ruby中,可以从超类定义子类中的常量吗?

在Ruby中,可以从超类定义子类中的常量吗?,ruby,class,constants,Ruby,Class,Constants,假设我有一个Ruby类,它被许多子类扩展。我希望这些子类中的每个都有一个名为FRIENDLY\u NAME的常量。显然,我可以编辑每个类并添加常量。但是,如果它没有在子类中指定,有没有办法从超类定义子类中的常量 例如,如果尚未定义FRIENDLY\u NAME,我可以将每个子类“FRIENDLY\u NAME设置为解调并加下划线的子类”类名。直到TracePoint 为了扩展我原来的问题,我有一个超类,我想扩展很多次: 类基类 结束 我希望该类的所有扩展版本都有一个友好的\u名称常量。当在子类

假设我有一个Ruby类,它被许多子类扩展。我希望这些子类中的每个都有一个名为
FRIENDLY\u NAME
的常量。显然,我可以编辑每个类并添加常量。但是,如果它没有在子类中指定,有没有办法从超类定义子类中的常量


例如,如果尚未定义
FRIENDLY\u NAME
,我可以将每个子类“
FRIENDLY\u NAME
设置为解调并加下划线的子类”类名。

直到
TracePoint

为了扩展我原来的问题,我有一个超类,我想扩展很多次:

类基类
结束
我希望该类的所有扩展版本都有一个
友好的\u名称
常量。当在子类中显式指定时,这将是常量的值。例如:

class子类1
因此:

然而,也许我还有另一个子类,我没有定义常量。例如:

class子类2
这就是我在没有常数的情况下得到的结果(显然):

如何添加该常数?您可以将
self.inherited
添加到超类中。每次扩展超类时都会调用此方法。在
模块
上还有一个名为
const_set
的方法,因此我可以在子模块上自动设置常量,如下所示:

类基类
def self.inherited(子项)
child.const\u集(:友好名称,child.NAME)
结束
结束
这对于
子类2
来说非常有效:

pry(main)> Subclass2::FRIENDLY_NAME
=> "Subclass2"
但是,它会为
子类1

(pry):10: warning: already initialized constant Subclass1::FRIENDLY_NAME
(pry):3: warning: previous definition of FRIENDLY_NAME was here
最初,我尝试使用
const\u defined?
方法来检查
友好名称
常量是否已经定义。问题是,
self.inherited
方法在子类中定义常量之前被调用。基本上,只要Ruby看到
,它就会运行
self.inherited

最终我找到了。答案是使用
TracePoint

TracePoint
是一个允许我们处理代码中事件的类。这可能是在执行一行代码、调用方法、引发错误等情况下发生的。我们关心的是
:end
事件,它发生在类或模块定义完成时

知道了这一点,我们可以像这样更新我们的
self.inherited
方法:

类基类
def self.inherited(子项)
跟踪点。跟踪(:end)do | t|
如果child==t.self
除非定义了child.const(友好名称)
child.const\u集(:友好名称,child.code)
结束
结束
结束
结束
结束

现在,
子类1
子类2
都有一个
友好名称
常量,但都不会产生警告

FWIW,我可以在超类中使用类似于
child.const\u set(:FRIENDLY\u NAME,'foo')
的东西,来自
self.inherited
,但这给了我一个警告,我正在重新定义一个常量,尽管我还没有定义它。“警告:已初始化常量”更正:警告来自一个类,我在该类中设置了
FRIENDLY_NAME
常量。问题是超类中的
self.extended
是在子类中定义常量之前执行的,如果该常量不存在,我将在那里设置该常量。因此,当我试图设置其实际值时,警告实际上来自子类:/这很有趣,但不是常数的好例子。您实际上是在跳转,试图让它表现出方法继承的工作方式,因此我将使用非常简单的类级方法,几乎所有Ruby开发人员都能理解,并且不需要对不太知名的Ruby特性(如
TracePoint
)有任何专门知识:,你说得对,类方法正是我要做的。不过,就像你说的,这很有趣。
pry(main)> Subclass2::FRIENDLY_NAME
=> "Subclass2"
(pry):10: warning: already initialized constant Subclass1::FRIENDLY_NAME
(pry):3: warning: previous definition of FRIENDLY_NAME was here