情况
我写了以下代码。
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
方法的情况下修复此编译错误。
我尝试了什么,我研究了什么
- Crystal语言不允许使用安全导航运算符
- 只有当wheel变量是truthy时才执行
diameter
方法,如TypeScript中所示。下面给出了一个示例
def gear_inches
if wheel
ratio * wheel.diameter
else
0
end
end
问题到此为止。如果你能给我任何建议,我将不胜感激。
在并发程序中,实例变量的值可以在任意两次访问之间发生变化。getter wheel
使wheel
只返回实例变量@wheel
。因此,在检查if wheel
和wheel.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