如果 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
。