在这种情况下,我如何处理好零



情况

我写了以下代码。

class Gear
getter :chainring, :cog, :wheel
def initialize(@chainring : Int32, @cog : Int32, @wheel : Wheel?)
end
def ratio
chainring / cog.to_f
end
def gear_inches
ratio * wheel.diameter
end
end

然后发生以下编译错误

$ crystal run  gear.cr 
Showing last frame. Use --error-trace for full trace.
In bicycle.cr:12:19
12 | ratio * wheel.diameter

我想做的事

我想在不使用try方法的情况下修复此编译错误。

我尝试了什么,我研究了什么

  1. Crystal语言不允许使用安全导航运算符
  2. 只有当wheel变量是truthy时才执行diameter方法,如TypeScript中所示。下面给出了一个示例
def gear_inches
if wheel
ratio * wheel.diameter
else
0
end
end

问题到此为止。如果你能给我任何建议,我将不胜感激。

在并发程序中,实例变量的值可以在任意两次访问之间发生变化。getter wheel使wheel只返回实例变量@wheel。因此,在检查if wheelwheel.diameter中的第二次调用之间,Crystal无法判断该值不可能更改。

通常的解决方案是将值分配给一个局部变量,这样Crystal就可以推断出值何时不能改变:

record Wheel, diameter : Int32
class Gear
getter :chainring, :cog, :wheel
def initialize(@chainring : Int32, @cog : Int32, @wheel : Wheel?)
end
def ratio
chainring / cog.to_f
end
def gear_inches
(wheel = self.wheel) ? ratio * wheel.diameter : 0
end
end
gear = Gear.new(1, 2, Wheel.new(3))
puts gear.gear_inches

在许多情况下,一个很好的选择是看看你是否能找到一个默认值来内部返回你的可选字段:

record Wheel, diameter : Int32
class Gear
getter :chainring, :cog
def initialize(@chainring : Int32, @cog : Int32, @wheel : Wheel?)
end
def ratio
chainring / cog.to_f
end
def gear_inches
ratio * wheel.diameter
end

private def wheel
@wheel || Wheel.new(0)
end
end
gear = Gear.new(1, 2, nil)
puts gear.gear_inches

最新更新