Ruby中如何在父类访问子类定义的常量,解决调用报错问题
Ruby父类访问子类常量的解决方法
报错原因
- 你遇到的报错本质是Ruby常量的查找规则导致的:默认情况下常量是词法作用域查找,你在
Vehicle类的to_s方法中直接写VEHICLE_TYPE时,Ruby只会在Vehicle类的作用域下查找对应常量,不会自动到子类作用域查找。 - 写
self.VEHICLE_TYPE报错的原因是常量不属于实例方法,你这种写法是尝试调用实例的VEHICLE_TYPE方法,自然会提示方法不存在。
方案1:适配现有常量设计的修改
只需要调整to_s方法中的常量引用方式,通过实例的类对象主动查找子类常量即可:
class Vehicle # 其余代码保持不变 def to_s "My #{self.class::VEHICLE_TYPE} is a #{self.model} #{self.year} of color #{self.color}." end end
self.class会返回当前实例所属的类(也就是你实例化的MyCar或者MyTruck子类),::是Ruby的常量查找运算符,就能正确找到子类中定义的VEHICLE_TYPE常量。
如果不希望有人直接实例化Vehicle时报错,可以在Vehicle类中也定义一个兜底的VEHICLE_TYPE常量,或者将Vehicle设为抽象类禁止直接实例化。
方案2:更符合面向对象设计的实现
如果不想依赖常量查找规则,也可以用方法重写的方式实现,逻辑更清晰也更灵活:
class Vehicle attr_accessor :color, :curr_speed attr_reader :year, :model def initialize(y, c, m) @year = y @color = c @model = m end # 定义抽象方法,要求子类必须实现 def vehicle_type raise "子类必须实现vehicle_type方法" end def to_s "My #{vehicle_type} is a #{self.model} #{self.year} of color #{self.color}." end end class MyCar < Vehicle def vehicle_type 'car' end end class MyTruck < Vehicle def vehicle_type 'truck' end end
这种方式完全避免了常量查找的规则问题,也符合面向对象的多态设计思路。
内容的提问来源于stack exchange,提问作者jampamatos
相关产品推荐
相关产品推荐

