3

以下代码运行良好并打印“5.0”

$x : Float64
$y : Float64
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y

现在,我将代码更改为支持“nil”。

$x : Float64?
$y : Float64?
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y if !$x.nil? && !$y.nil?

但是,此代码报告以下错误消息。

没有重载匹配 'Float64#+' 类型 (Float64 | Nil)
重载是:
 - Float64#+(其他:Int8)
 - Float64#+(其他:Int16)
 - Float64#+(其他:Int32)
 - Float64#+(其他:Int64)
 - Float64#+(其他:UInt8)
 - Float64#+(其他:UInt16)
 - Float64#+(其他:UInt32)
 - Float64#+(其他:UInt64)
 - Float64#+(其他:Float32)
 - Float64#+(其他:Float64)
 - 数字#+()
找不到这些类型的重载:
 - Float64#+(无)

    如果 !$x.nil 则放 $x + $y?&& !$y.nil?

如果 $x 或 $y 为 nil,我想停止方法“#+()”的调用,如果两者都是 Float64,则打印计算结果。

这种情况的最佳做法是什么?


在上面的代码中,我简化了这个问题的代码。结果,不由自主地改变了问题的含义。我实际上想问下面的代码。

class Xyz
  property a, b
  @a : Float64?
  @b : Float64?

  def initialize
    @a = nil
    @b = nil
  end

  def do_calc
    if !@a.nil? && !@b.nil?
      puts @a + @b
    else
      puts "We can't calculate because '@a or @b has nil."
    end
  end
end

x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc

此代码报告以下错误。

实例化'Xyz#do_calc()'

x.do_calc
  ^~~~~~~

在 ./a.cr:15 中:没有重载匹配 'Float64#+' 类型 (Float64 | Nil)
重载是:
 - Float64#+(其他:Int8)
 - Float64#+(其他:Int16)
 - Float64#+(其他:Int32)
 - Float64#+(其他:Int64)
 - Float64#+(其他:UInt8)
 - Float64#+(其他:UInt16)
 - Float64#+(其他:UInt32)
 - Float64#+(其他:UInt64)
 - Float64#+(其他:Float32)
 - Float64#+(其他:Float64)
 - 数字#+()
找不到这些类型的重载:
 - Float64#+(无)

      放@a + @b

我怎样才能避免这个错误?

4

2 回答 2

4

请务必阅读有关 if 并检查 nil 的文档:https ://crystal-lang.org/docs/syntax_and_semantics/if_var.html和https://crystal-lang.org/docs/syntax_and_semantics/if_var_nil.html

这仅适用于局部变量,因此您需要先将值分配给局部变量。

附带说明一下,从 Crystal 0.19.0 开始,该语言中不再存在全局变量。

于 2016-09-07T15:17:37.847 回答
0

我认为这是因为编译无法推断if子句内的类型,它不像动态类型语言。如果@a类型是 aNil怎么办?我们没有类型的+运算符Nil。因此,您已经声明@a并且@bFloat64明确的。

class Xyz
  property a, b
  @a : Float64?
  @b : Float64?

  def initialize
    @a = nil
    @b = nil
  end

  def do_calc
    if !@a.nil? && !@b.nil?
      puts @a.as(Float64) + @b.as(Float64)
    else
      puts "We can't calculate because '@a or @b has nil."
    end
  end
end

x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc

或者使用#tryObject抽象类派生的(Float 和 Nil 派生它)

class Xyz
  property a, b
  @a : Float64?
  @b : Float64?

  def initialize
    @a = nil
    @b = nil
  end

  def do_calc
    if !@a.nil? && !@b.nil?
      @a.try do |a|
        @b.try do |b|
          puts a + b
        end
      end
    else
      puts "We can't calculate because '@a or @b has nil."
    end
  end
end

x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc

最佳实践

由你决定。对我来说,这取决于上下文。我认为 using#try更好,因为它更明确,它解释了变量可能是一种nil类型。但在这种情况下使用#try非常冗长,所以我会选择第一个解决方案。

于 2019-12-03T15:18:18.557 回答