Swift 中 struct init 的编译器错误

Compiler errors for struct init in Swift

我有以下结构:

struct Person {
   let name: String
   let age: Int
   let assets: Double
}

为了初始化一个人,我想给它传递一个包含姓名和年龄的字典,以及计算资产的信息:

public init(info: [String : AnyObject]) {
        if let name = info["name"] as? String {
            self.name = name
        }

        if let age = info["age"] as? Int {
            self.age = age
        }

        if let assets = info["assets"] as? [String : AnyObject] {
            calculateAssets(assets: assets)
        }
    }

    mutating func calculateAssets(assets: [String : AnyObject]) {
        self.assets = 1+2+3.4  // really do this with info from the dictionary
    }

使用此设置,出现两个编译器错误:

  1. 'self' 在所有存储属性初始化之前使用
  2. Return 来自初始化器而不初始化所有存储的属性

按照编译器的建议,我为每个 属性 添加了一个默认值,并将它们更改为 var:

struct Person {
    var name: String = ""
    var age: Int = 0
    var assets: Double = 0.0

// init ...
}

事实上,编译器错误已经消失。

但是我进行这些更正是否在正确的轨道上?

你得到了编译器错误,因为当你设置它们时你的变量是not inited。(你将它们定义为inited)。这就是为什么在第二种情况下,当您 init 将它们设置为 nil 值时,error 消失了。对于这种情况,Swift 有 optionals。可以同时为 nil 和一个值。检查 here。您可以添加 ? 并使变量 optional.

struct Person {
    var name: String?
    var age: Int?
    var assets: Double?

// init ...
}

问题是,在您的 init 函数中,您 可能 初始化变量,但您不能确定,因为 if语句可以是 false。这就是编译器给你错误的原因(也是因为你试图在另一个函数中调用 self.assets 而变量可能仍未初始化 - 所以你至少需要将这个更改为 var).

如果您不能确定 info 字典中的值是否有效,您应该将变量更改为 var

现在你有两个选择:

  • 给你的变量一个默认值(就像你在你的例子中所做的那样)
  • 将您的变量声明为 Optionals(如@Özgür 所建议)。

您的选择取决于什么更有意义。如果您的默认值对您的情况有意义,并且您可以使用具有这些值的变量,那么我会接受它。

否则,你应该选择OptionalsOptionals 显然有一个优点,那就是你不需要初始化它们,但缺点是你需要在以后使用它们时隐式或显式地解包它们(使用 ?!).

如果 - 出于任何原因 - 你可以确定 info 字典中的值是有效的 - 你也可以离开你的 nameage 作为常量 (let) 并在分配字典值时显式展开字典值:

self.name = info["name"] as! String

self.age = info["age"] as! Int

但正如我所说,这只有在 info["name"]info["age"] 包含有效值时才有效,否则您将遇到运行时异常。所以 "default value" 或 "Optional" 选项是安全和干净的选择,而这是快速和肮脏的方式。