Swift 为什么空检查不好/如果可选项';什么是空的?
我已经阅读了一些类似问题的答案和一些教程,但没有一本能解决我的主要困惑。我是本地Java程序员,但我也用Swift编程 为什么我要用可选的而不是空的 我读过这样的文章,它减少了空检查和错误,但是这些都是必要的,或者可以通过干净的编程轻松避免 我也读过,所以所有的引用都成功了(而且Swift 为什么空检查不好/如果可选项';什么是空的?,swift,kotlin,null,optional,Swift,Kotlin,Null,Optional,我已经阅读了一些类似问题的答案和一些教程,但没有一本能解决我的主要困惑。我是本地Java程序员,但我也用Swift编程 为什么我要用可选的而不是空的 我读过这样的文章,它减少了空检查和错误,但是这些都是必要的,或者可以通过干净的编程轻松避免 我也读过,所以所有的引用都成功了(而且val length=text?.length)。但我认为这是一件坏事或用词不当。如果我调用length函数,我希望它包含一个长度。如果没有,代码应该在那里处理它,而不是继续 我遗漏了什么?选项提供了清晰的类型。Int存
val length=text?.length
)。但我认为这是一件坏事或用词不当。如果我调用length函数,我希望它包含一个长度。如果没有,代码应该在那里处理它,而不是继续
我遗漏了什么?选项提供了清晰的类型。Int存储实际值-始终,而可选Int(即Int?)存储Int或nil的值。可以说,这种显式的“dual”类型允许您创建一个简单的函数,该函数可以清楚地声明它将接受和返回什么。如果您的函数只是简单地接受一个实际的Int并返回一个实际的Int,那么就太好了
func foo(x: Int) -> Int
但是,如果您的函数希望允许返回值为nil,参数为nil,则必须显式将其设置为可选:
func foo(x: Int?) -> Int?
在其他语言(如Objective-C)中,对象可以始终为零。C++中的指针也可以是零。因此,在Obj-C中接收的任何对象或C++中接收的任何指针都应该被检查为零,以防您的代码所期望的不是(真实对象或指针)。
在Swift中,关键是您可以声明非可选的对象类型,因此您将这些对象交给的任何代码都不需要进行任何检查。他们可以安全地使用这些对象,并且知道它们是非空的。这是Swift optionals的一部分力量。如果您收到一个可选的,那么当您需要访问它的值时,您必须显式地将它解压为它的值。那些使用Swift编写代码的人总是尽可能地将其函数和属性设置为非可选的,除非他们确实有理由将其设置为可选的
Swift optionals的另一个优点是所有用于处理optionals的内置语言结构,使代码编写更快、阅读更清晰、更紧凑。。。省去了很多麻烦,不用检查和解包一个可选的和等价的,你必须用其他语言做的
nil凝聚算子(??)是一个很好的例子,如if-let和guard等
总之,optionals鼓励并强制在代码类型检查中执行更显式的类型检查,这是由编译器而不是在运行时完成的。当然,你可以用任何语言编写“干净”的代码,但用Swift编写代码要简单得多,自动化程度也更高,这在很大程度上要归功于它的可选代码(以及非可选代码!)
可以有更多,但这些是非常有用的。TL/DR:编译器也可以更严格地避免使用干净编程可以避免的空检查。您所说的必要的空检查可以由编译器以更严格的方式强制执行。Optionals是使之成为可能的类型构造
var length=text?.length
这实际上是一个很好的例子,说明了可选项是有用的。如果文本没有值,那么它也不能有长度。在Objective-C中,如果text
为零,则您发送的任何消息都不会执行任何操作,并返回0。这一事实有时是有用的,它可以跳过大量的零检查,但也可能导致微妙的错误
另一方面,许多其他语言指出了这样一个事实:当代码执行时,通过立即崩溃,您已经向nil指针发送了一条消息。这使得在开发过程中更容易发现问题,但是当运行时错误发生在用户身上时,就不会那么严重了
Swift采取了一种不同的方法:如果文本没有指向有长度的东西,那么就没有长度。可选的不是指针,而是一种有值或无值的类型。您可以假设变量length
是一个Int
,但实际上它是一个Int?
,这是一种完全不同的类型
如果我调用length函数,我希望它包含一个长度。如果没有,代码应该在那里处理它,而不是继续
如果text
为nil,则没有对象可向其发送length
消息,因此length
甚至从未被调用,结果为nil。有时这很好——如果没有文本
,也就不可能有长度
,这是有道理的。您可能不在乎这一点-如果您准备在文本中绘制字符
,那么没有长度
这一事实不会困扰您,因为反正没有什么可绘制的。text
和length
的可选状态迫使您处理这样一个事实,即这些变量在您需要值的地方没有值
让我们看一个更具体的版本:
var text : String? = "foo"
var length : Int? = text?.count
这里,text
有一个值,因此length
也会得到一个值,但是length
仍然是可选的,所以在
var text : String? = nil
var length : Int? = text?.count
var text : String? = "foo"
var length : Int = text.count
var text : String? = "foo"
var length : Int = text!.count
var text : String? = nil
var length : Int = text!.count
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
var text : String = "foo"
var length : Int = text.count