如果 var.nil?¶
如果 if 的条件是 var.nil? 那么编译器知道 then 分支中的 var 类型为 Nil,并且知道 else 分支中的 var 类型为非 Nil。
a = some_condition ? nil : 3
if a.nil?
# here a is Nil
else
# here a is Int32
end
实例变量¶
通过 if var.nil? 进行的类型限制只对局部变量有效。类似于上面代码示例中的实例变量类型仍然可以为空,并且由于 greet 在 unless 分支中需要 String 因此会抛出编译错误。
class Person
property name : String?
def greet
unless @name.nil?
puts "Hello, #{@name.upcase}" # Error: undefined method 'upcase' for Nil (compile-time type is (String | Nil))
else
puts "Hello"
end
end
end
Person.new.greet
您可以通过首先将值存储在局部变量中来解决此问题
def greet
name = @name
unless name.nil?
puts "Hello, #{name.upcase}" # name will be String - no compile error
else
puts "Hello"
end
end
这是 Crystal 中多线程的副产品。由于存在 Fibers,Crystal 在编译时不知道在 if 分支中到达使用位置时实例变量是否仍然为非 Nil。