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。对象,如果文件在提供的路径中不存在。如果初始化成功,您可以使用可选绑定来解包可用初始化程序的结果。“
即使这个问题已经存在了一段时间,我也会尝试一下,因为我认为一些示例源代码对于理解init!
是有用的init!
是为了(至少是为了我)。
隐式展开的可选项提供了两个有价值的东西:
- 程序员的便利(因此您不必在可选变量的末尾输入’
?
‘),以及 - 运行时效率,因为它允许您只测试一次可选的
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