Ruby:混合、继承和常量名称解析

  • 本文关键字:常量 混合 继承 Ruby ruby
  • 更新时间 :
  • 英文 :


我的程序具有以下结构:

module M1
class A
def action
C.new.foo
end
end
class C
def foo
puts "M1::C foo"
end
end
end

module M2
class A
def action
C.new.foo
end
end
class C
def foo
puts "M2::C foo"
end
end
end

由于M1::AM2::A共享相同的代码,我一直在考虑将公共代码放在单独的类(或模块(中并从中继承(包含它(。像这样:

class ABase
def action
C.new.foo
end
end
module M1
class A < ABase
end
class C
def foo
puts "M1::C foo"
end
end
end

module M2
class A < ABase
end
class C
def foo
puts "M2::C foo"
end
end
end

但是,当我尝试时,我在名称解析uninitialized constant ABase::C遇到了麻烦。在这种情况下,实现代码共享的正确方法是什么?

由于常量是根据定义范围而不是在继承的作用域中解析的,因此您需要使用方法调用来桥接它:

class ABase
def action
# Within this scope only constants defined in `ABase` are resolved.
# As ABase::C and ::C (root-level) don't exist, C can't be resolved.
# However, a method `c` defined in a subclass will be.
c.new.foo
end
end
module M1
class A < ABase
def c
C
end
end
class C
def foo
puts "M1::C foo"
end
end
end
module M2
class A < ABase
# This resolves C as either M2::A::C, M2::ABase::C, M2::C or ::C,
# whichever it finds first.
def c
C
end
end
class C
def foo
puts "M2::C foo"
end
end
end

然后你会得到预期的结果:

M1::A.new.action
# => M1::C foo
M2::A.new.action
# => M2::C foo

最新更新