简体   繁体   English

在这个例子中使用隐式解包的可选项有什么意义?

[英]What is the point of using implicitly unwrapped optional in this example?

This is from the docs, section Failable Initializers for Classes : 这是来自docs, 类的Failable Initializers部分:

class Product {

     let name: String!
     init?(name: String) {
           self.name = name
           if name.isEmpty { return nil }
     }
}


if let bowTie = Product(name: "") {
   // no need to check if bowTie.name == nil
   print("The product's name is \(bowTie.name)")
}

This is described like: 这描述如下:

In the example above, the name property of the Product class is defined as having an implicitly unwrapped optional string type (String!). 在上面的示例中,Product类的name属性被定义为具有隐式解包的可选字符串类型(String!)。 Because it is of an optional type, this means that the name property has a default value of nil before it is assigned a specific value during initialization. 因为它是可选类型,这意味着在初始化期间为name属性分配特定值之前,name属性的默认值为nil。 This default value of nil in turn means that all of the properties introduced by the Product class have a valid initial value. 此默认值nil反过来意味着Product类引入的所有属性都具有有效的初始值。 As a result, the failable initializer for Product can trigger an initialization failure at the start of the initializer if it is passed an empty string, before assigning a specific value to the name property within the initializer. 因此,如果在初始化程序中为name属性指定特定值之前传递空字符串,那么Product的初始化程序可以在初始化程序启动时触发初始化失败。

Take a look at the last sentence: 看看最后一句话:

As a result, the failable initializer for Product can trigger an initialization failure at the start of the initializer if it is passed an empty string, before assigning a specific value to the name property within the initializer. 因此,如果在初始化程序中为name属性指定特定值之前传递空字符串,那么Product的初始化程序可以在初始化程序启动时触发初始化失败。

This can't be seen from the provided code . 从提供的代码中看不到这一点。 In the provided code, it can be seen that assignment has occurred before return nil part, and either String (non-optional) or String? 在提供的代码中,可以看到在return nil部分之前发生了赋值,并且String(非可选)或String? (optional) would work. (可选)会起作用。

Another thing is that in provided example, it make no sense to use an implicitly unwrapped optional if it is defined as constant. 另一件事是,在提供的示例中,如果将其定义为常量,则使用隐式展开的可选项是没有意义的。 Constants have to be initialized to default values right before the init is finished. 必须在init完成之前将常量初始化为默认值。

Any thoughts on this, or does anybody see the reason not to file a radar about this? 对此有任何想法,或者是否有人看到不提出雷达的理由? Maybe I am missing something ? 也许我错过了什么? I have an idea actually why is implicitly unwrapped optional used in here, but it is a bad example. 我有一个想法实际上为什么隐式解包可选在这里使用,但它是一个坏的例子。 For me, this would make more sense: 对我来说,这会更有意义:

class Product {

    var name: String! //let is changed to var

    init?(name: String) {

       if name.isEmpty { return nil } //Check here if passed value is non-empty
       self.name = name
    }
}

This way, a initialization failure can be triggered before the any assignment to the name property. 这样,可以在对name属性进行任何赋值之前触发初始化失败。

All your concerns about misleading documentation are right. 您对误导性文档的所有疑虑都是正确的。

Also, please note that in Swift 2.2 returning early from a failable initializer does work , even before all properties are initialized: 此外,请注意,在Swift 2.2中,从可用的初始化程序返回早期确实有效 ,甚至在所有属性初始化之前:

class Product {
    let name: String
    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
}

Another change is that deinit is not called any more when returning nil from the failable initializer. 另一个变化是, deinit 不叫从failable初始化更多的返回时为零。

From Xcode 7.3 beta 2 Release Notes : 来自Xcode 7.3 beta 2 发行说明

Inside a class, a designated initializer that is either failable ( init?() ) or throwing ( init() throws ) is allowed to exit before initializing all stored properties and calling super.init() . 在类中,允许在初始化所有存储的属性并调用super.init()之前退出指定的初始化程序,该程序可以是可用的( init?() )或init() throwsinit() throws super.init() This behavior is supported, making designated initializers more consistent with convenience initializers. 支持此行为,使指定的初始化程序与便捷初始化程序更加一致。 Convenience initializers can also fail before performing a self.init() delegation. 在执行self.init()委派之前,便捷初始化程序也可能失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM