init的目的是什么! 可用的初始化程序?

Apple Swift编程语言指南提到了init的存在! 初始化程序,但没有提供任何示例。 ( 在此页面中搜索init!)

我理解使用init?声明的普通可用初始化程序,但我不能满足其他版本的需要。 需要什么? 有人能提供一个例子吗?

这有两个目的:

  • 导入Swift不知道的Cocoa API时。 如果Swift不知道初始化程序是否可以返回nil,则用它来注释! 所以开发人员知道那里可能有一个零隐藏,如果实际上没有理由,就不会强迫开发人员测试nil。

  • 出于同样的原因,隐式解包的选项在其他环境中使用(在某些情况下,您可能愿意交换编译时安全性以增加便利性)。

我相信它的使用绝对相同! 和期权一样。 init? 将返回一个可选项。 init! 将返回一个隐式解包的可选项。

调用Obj-C API需要隐式解包的选项,您不确定它是否可以返回可选项。 因此,您使用隐式展开的可选项,它的行为类似于非可选类型,但如果返回可选项,它将崩溃。

请注意,当引入Swift时,大多数Obj-C框架仅返回隐式解包的选项,但目前很多都返回选项或非可选类型,因为Apple正在查看代码并检查它们是否可以返回可选项。 init! Apple尚未正确标记初始化程序的所有地方都需要。

好问题Matteo,我正在寻找同一个问题的答案,因为init! 没有意义(如果它总是初始化一个对象,我们不需要可选),但我还没有找到任何明确的答案。

我认为这是因为Apple还没有完成他的工作:“ ……自己的Objective-C类,以及尚未审计的框架中的类,初始化器作为init导入 ……

也许适合你,“与Objective-C API交互”中的文字(Apple)

  • “在Objective-C中,初始化器直接返回它们初始化的对象。为了在初始化失败时通知调用者,Objective-C初始化器可以返回nil。在Swift中,这种模式被内置到称为可用初始化的语言特性中。已经审计了iOS和OS X系统框架中的C初始化程序,以指示初始化是否会失败。这些Objective-C初始化程序作为init(…)导入 – 如果初始化不能失败 – 或初始化?(…)如果初始化在你自己的Objective-C类和尚未审计的框架中的类中,初始化器被导入为init!(…)。例如,NSString(contentsOfFile :)初始化器可能无法初始化NSString。对象,如果文件在提供的路径中不存在。如果初始化成功,您可以使用可选绑定来解包可用初始化程序的结果。“

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html

即使这个问题已经存在了一段时间,我也会尝试一下,因为我认为一些示例源代码对于理解init!是有用的init! 是为了(至少是为了我)。

隐式展开的可选项提供了两个有价值的东西:

  1. 程序员的便利(因此您不必在可选变量的末尾输入’ ? ‘),以及
  2. 运行时效率,因为它允许您只测试一次可选的nil ,然后(只要它是非零)使用它的unwrapped(即direct)值。

但重要的是,隐式展开的可选项仍然是可选的,这意味着它可以测试nil

现在,至于init!的实用程序init! -failable初始化程序,我们可以用它来获得我上面列出的两个东西(方便性和运行时效率),同时仍然允许init函数失败(即返回nil )。 正如其他人所说,这可以通过调用Objective-C API来实现,但它也可以直接从您可能选择编写的代码中发生。 这是一个例子:

 class A { init!() { return nil // something happens that causes init to fail } } var a:A! = A() // variable 'a' *is* an optional, and also nil if a != nil { // and we can test it! print( "a is not nil" ) } else { print( "a is nil, better not use it." ) } 

在这个例子中,我给自己一种方法来失败class A的初始化,是的,可以用init?很容易地完成它init? 方法,但是当我创建一个A类型的对象时,我可能只需要测试初始化​​成功或失败一次 – 毕竟,我要么创建了A还是我没有 – 然后如果它不是nil我只想使用直接值。 所以在这种情况下,使用init! -failable初始化程序非常方便。

它在两种情况下有所不同:

如果你写

 let x: myclass = myclass(...) 

初始化? 因为init会不会编译? 返回一个可选的; 在里面! 如果init方法返回nil,将编译但崩溃。

如果你写

 let x = myclass(...) 

然后它将在任何一种情况下编译,并且在任何一种情况下都不会崩溃。 区别在于,在一种情况下,x具有myclass类型? 而在另一种情况下键入myclass! 行为明显不同。

如果您编写以下两个之一:

 let x: myclass? = myclass(...) let x: myclass! = myclass(...) 

那么init是否无关紧要! 或者初始化? 使用了,因为任何一个都可以分配给一个可选的而不会崩溃。

init初始化程序与其他语言中的类的构造函数相同。 它设置初始值并执行一些初始操作(比如检查值是否为大等)。 有趣:它也需要参数,可以重载。

例:

 struct Celsius { var temperatureInCelsius: Double init(fromFahrenheit fahrenheit: Double) { temperatureInCelsius = (fahrenheit - 32.0) / 1.8 } init(fromKelvin kelvin: Double) { temperatureInCelsius = kelvin - 273.15 } } let boilingPointOfWater = Celsius(fromFahrenheit: 212.0) let freezingPointOfWater = Celsius(fromKelvin: 273.15) 

因此,当您调用struct时,它会根据您的调用参数返回不同的值。

有关详细信息,请访问: http : //www.informit.com/articles/article.aspx? p = 2246797