You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Gear类gear_inches方法硬编码依赖Wheel类的扩展性问题及相关疑问

Gear类gear_inches方法硬编码依赖Wheel类的扩展性问题及相关疑问

嘿,我来帮你把这个困惑捋明白~

首先你可能误解了这里的场景:不是要让Disk或者Cylinder去调用Gear的gear_inches方法,而是希望同一个Gear实例可以和不同的、具备直径属性的部件(比如Disk、Cylinder)协作,计算出对应的齿轮英寸值。原代码的问题就出在Gear把自己和Wheel绑定得太死了,导致它没办法和其他部件配合。

咱们先看原代码的核心问题:
在Gear的gear_inches方法里,它直接硬编码创建了Wheel.new(rim, tire)实例,这相当于Gear在说:“我只跟Wheel这个类合作,其他玩意儿一概不认”。哪怕Disk或者Cylinder这类对象天生就有diameter方法,Gear也完全没办法和它们协作——因为它在代码里写死了必须用Wheel类。

举个实际场景:假设你现在要做一个机械模拟程序,里面除了带轮胎的车轮,还有实心圆盘(Disk)、圆柱滚轮(Cylinder),这些部件都有直径,都能和齿轮配合计算齿轮英寸。但原代码里的Gear,不管你给它传的是Disk还是Cylinder的参数,它都会在gear_inches里强行创建一个Wheel实例,根本不会用你给的其他部件,自然算不出正确的结果。

那怎么解决这个问题?核心思路是把依赖的对象“注入”给Gear,而不是让Gear自己创建。比如修改Gear的设计,让它初始化时接收一个具备diameter方法的对象(不管是Wheel、Disk还是别的),这样Gear就只关心这个对象有没有diameter方法,而不关心它具体是什么类。

修改后的代码大概是这样:

class Gear
  attr_reader :chainring, :cog, :rotor

  # 初始化时接收一个带diameter方法的部件对象
  def initialize(chainring, cog, rotor)
    @chainring = chainring
    @cog = cog
    @rotor = rotor
  end

  def ratio
    chainring / cog.to_f
  end

  def gear_inches
    # 直接用传入的rotor的diameter,不再硬编码创建Wheel
    ratio * rotor.diameter
  end
end

# 现在可以随便加其他带diameter的类
class Disk
  attr_reader :diameter

  def initialize(diameter)
    @diameter = diameter
  end
end

class Cylinder
  attr_reader :radius

  def initialize(radius)
    @radius = radius
  end

  def diameter
    radius * 2
  end
end

# 使用示例:和Wheel配合
gear_with_wheel = Gear.new(52, 11, Wheel.new(26, 1.5))
puts gear_with_wheel.gear_inches # 输出和原代码一样的结果

# 和Disk配合
gear_with_disk = Gear.new(52, 11, Disk.new(30))
puts gear_with_disk.gear_inches # 正常计算齿轮英寸

# 和Cylinder配合
gear_with_cylinder = Gear.new(52, 11, Cylinder.new(15))
puts gear_with_cylinder.gear_inches # 同样能计算

这样一来,Gear就摆脱了对Wheel类的硬编码依赖,只要是有diameter方法的对象,它都能愉快协作——这就是面向对象里“依赖倒置”和“鸭子类型”的好处,代码的扩展性一下子就上来了。

备注:内容来源于stack exchange,提问作者current_user

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 08:08:10