if var.nil?¶
如果 if
的條件是 var.nil?
,則編譯器會知道 then
分支中 var
的型別為 Nil
,而在 else
分支中則已知為非 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
的。