Apple Swift编程语言指南提到了init的存在!初始化程序,但没有提供任何示例。 (搜索init!in this page)
我理解使用用init?声明的普通可用初始化程序,但是我没有得到这个其他版本的需要。需要什么?有人可以提供一个例子吗?
答案 0 :(得分:2)
这有两个目的:
导入Swift不知道的Cocoa API时。如果Swift不知道初始化程序是否可以返回nil,则用它来注释它!所以开发人员知道那里可能有一个零隐藏,如果实际上没有理由,就不会强迫开发人员测试nil。
出于同样的原因,在其他情况下使用隐式解包的选项(您可能愿意在某些情况下交换编译时安全性以增加便利性。)
答案 1 :(得分:1)
我相信它与选项中的!
绝对相同。 init?
将返回一个可选项。 init!
将返回一个隐式解包的可选项。
调用Obj-C API需要隐式解包的选项,您不确定它是否可以返回可选项。因此,您使用隐式展开的可选项,它的行为类似于非可选类型,但如果返回可选项,它将崩溃。
请注意,当引入Swift时,大多数Obj-C框架仅返回隐式解包的选项,但目前很多都返回选项或非可选类型,因为Apple正在查看代码并检查它们是否可以返回可选项。在Apple尚未正确标记初始化程序的任何地方都需要init!
。
答案 2 :(得分:1)
好问题Matteo,我正在为同样的问题寻找答案,因为 init!没有意义(如果它总是初始化一个对象,我们不需要可选),但我没有没有找到任何明确的答案。
我认为这是因为Apple还没有完成他的工作:“ ...自己的Objective-C类,以及尚未审核的框架中的类,初始化器被导入为 init ! ...... “
或许可以帮助你,“与Objective-C API交互”(Apple)中的文字
答案 3 :(得分:1)
即使这个问题已经存在了一段时间,我也会尝试一下,因为我认为一些示例源代码对于理解init!
的用途是有用的(至少它是对我来说。)
隐式展开的可选项提供了两个有价值的东西:
?
')nil
的可选项,然后(只要它是非nil
)使用其未包装(即直接)值。重要的一点是隐式展开的可选项仍是可选的,这意味着可以对nil
进行测试。
现在,关于init!
- 可用的初始化程序的实用程序,我们可以使用它来获取上面列出的两个内容(方便性和运行时效率),同时仍然允许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?
方法轻松完成它,但是当我创建一个类型为{的对象时{1}}我可能只需要测试初始化成功或失败一次 - 毕竟,我要么创建了A,要么我没有 - 并且之后如果它不是A
我只想使用直接值。所以在这种情况下,使用nil
- 可用的初始化器非常方便。
答案 4 :(得分:1)
它在两种情况下有所不同:
如果你写
let x: myclass = myclass(...)
然后初始化?因为init会不会编译?返回一个可选的;在里面!如果init方法返回nil,将编译但崩溃。
如果你写
let x = myclass(...)
然后它将在任何一种情况下编译,并且在任何一种情况下都不会崩溃。区别在于,在一种情况下,x具有myclass类型?而在另一种情况下键入myclass!行为明显不同。
如果您写下以下两种之一:
let x: myclass? = myclass(...)
let x: myclass! = myclass(...)
然后init是否无关紧要!或者初始化?使用了,因为任何一个都可以分配给一个可选的而不会崩溃。
答案 5 :(得分:-3)
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