【问题标题】:Swift Overload init()Swift 重载 init()
【发布时间】:2014-10-07 10:40:52
【问题描述】:

我将重载 Swift 中的 init 方法,我该如何实现呢?

这里我的代码不起作用

代码已删除

编辑:

这样就好办了

override init() {
    super.init();
}

init(title:String?) {
    super.init();
    self.title = title
}

convenience init(title:String?, imageName:String?) {
    self.init(title:title)
    self.imageName = imageName
}

convenience init(title:String?, imageName:String?, contentKey:String?) {
    self.init(title:title, imageName:imageName)
    self.contentKey = contentKey
}

【问题讨论】:

  • 什么不完全有效?你得到什么错误?我猜你需要为类引入的任何新属性提供值。然后拨打super.init()

标签: xcode swift overloading init


【解决方案1】:

更新答案

class Y { }
class X : Y {
    var title: String?
    var imageName: String?

    convenience override init() {
        self.init(title: nil, imageName: nil)
    }

    convenience init(title:String?) {
        self.init(title: title, imageName: nil)
    }

    init(title: String?, imageName: String?) {
        self.title = title
        self.imageName = imageName
        super.init()
    }
}
  • 使用最完整的初始化器作为指定初始化器。

    在这种情况下,init(title: String?, imageName: String?) 是唯一设置其所有属性的初始化程序,因此它应该是指定的初始化程序。

  • 在调用super.init()之前初始化您的属性。

    我的旧答案之所以有效,是因为 titleimageName 都是 var 并且是可选的。

    The Swift Programming Language: Initialization的两阶段初始化部分

    安全检查1

    指定的初始化程序必须确保其类引入的所有属性在委托给超类初始化程序之前都已初始化。


旧答案

我将示例插入到 Playground 中,这是我如何让它工作的:

class Y { }
class X : Y {
    var title: String?
    var imageName: String?

    override init() {

    }

    init(aTitle:String?) {
        super.init()
        self.title = aTitle
    }

    convenience init(aTitle:String?, aImageName:String?) {
        self.init(aTitle: aTitle)
        self.imageName = aImageName
    }
}
  • init(aTitle:String?, aImageName:String?) 不能调用 init(aTitle:) 并且仍然是指定初始化器,它必须是便利初始化器。
  • self.init 必须位于 init(aTitle:String?, aImageName:String?) 中的任何其他内容之前。
  • 初始化器必须传递参数名称self.init(aTitle)必须是self.init(aTitle: aTitle)

作为旁注,出于样式原因,我删除了不需要的分号并将super.init() 放在首位。

希望对您有所帮助。


更新

按照 Apple 的建议,应该只指定一个,其余的应该是便利初始化器。例如,如果您决定 init(aTitle:String?) 应该是指定的初始化程序,那么代码应该如下所示:

convenience override init() {
    self.init(aTitle: nil) // A convenience initializer calls the designated initializer.
}

init(aTitle:String?) {
    super.init() // Only the designated initializer calls super.init.
    self.title = aTitle
}

convenience init(aTitle:String?, aImageName:String?) {
    self.init(aTitle: aTitle)  // A convenience initializer calls the designated initializer.
    self.imageName = aImageName
}

有时您可能需要多次指定初始化程序,例如UIView,但这应该是一个例外,而不是规则。


更新 2

类应该有一个指定的初始化器。便利构造器将(最终)调用指定的构造器。

Initialization

一个类可能有多个初始化器。当初始化数据可以采用不同的形式或某些初始化程序为方便起见提供默认值时,就会发生这种情况。在这种情况下,其中一种初始化方法称为指定初始化器,它采用完整的初始化参数。

Multiple initializers

指定初始化器

采用完整的初始化参数的类的初始化器通常是指定的初始化器。子类的指定初始化程序必须通过向 super 发送消息来调用其超类的指定初始化程序。 便利(或次要)初始化器(可以包括 init)不调用 super。 相反,它们调用(通过给自己的消息)系列中的初始化器,并提供一个默认值对于未传递给它的参数。 本系列的最后一个初始化器是指定初始化器。

【讨论】:

  • 谢谢,当我有更多的重载init我必须写总是方便覆盖init(){ super.init(); } init(title:String?) { super.init(); self.title = title } 便利 init(title:String?, imageName:String?) { self.init(title:title) self.imageName = imageName } 便利 init(title:String?, imageName:String?, contentKey:String ?) { self.init(title:title, imageName:imageName) self.contentKey = contentKey }
  • 有两种初始化器:指定的和方便的。如果可能的话,您希望只有 1 个指定的初始化器,所有其他的都应该是便利初始化器(请参阅:Designated Initializers and Convenience Initializers)。
  • 失败,这没有任何作用
  • @JefferyThomas 您能否提供一个指向 Apple 建议的链接,其中提到应该只有一个指定的初始化程序?这种说法对我来说听起来不正确。谢谢
  • @0101 Apple 显然希望程序员使用尽可能少的指定初始化程序,其中一个是理想的数字。在我引用的参考文献中,假设只有一个。在您引用的参考文献中,他们指出,“一个类只有一个是很常见的”。鉴于这一切,我认为可以公平地说,一个类应该只有一个指定的初始化器,除非你有充分的理由需要更多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
  • 2015-01-03
  • 2015-10-20
  • 2020-06-07
  • 2016-09-02
  • 1970-01-01
相关资源
最近更新 更多