一尘不染

协议扩展初始化器

swift

我想知道在一个仅包含初始化功能并且仅打算在具体类中进行扩展的简单类中,对于等效于该初始值设定项的协议等效于什么。

因此,最简单的方法可能就是显示代码-我正在寻找与以下内容等效的协议扩展:

import UIKit

class Thing {
    var color:UIColor
    init(color:UIColor) {
        self.color = color
    }
}
class NamedThing:Thing {
    var name:String
    init(name:String,color:UIColor) {
        self.name = name
        super.init(color:color)
    }
}
var namedThing = NamedThing(name: "thing", color: UIColor.blueColor())

我期望代码看起来像这样:

protocol Thing {
    var color:UIColor {get set}
}
extension Thing {
    init(color:UIColor) {
        self.color = color
    }
}
class NamedThing:Thing {
    var name:String
    var color:UIColor
    init(name:String,color:UIColor) {
        self.name = name
        self.init(color:color)
    }
}

我已经看到其他StackOverflow问题中建议的解决方案,但是我不确定它们是否有效,也不确定在类初始化程序中专门解决此问题。


阅读 226

收藏
2020-07-07

共1个答案

一尘不染

您必须提供一个有效的初始化链来创建类的实例,并且这限制了协议中初始化程序的选择。

由于不能确定协议是否涵盖使用该协议的类的所有成员,因此您在协议中声明的任何初始化器都需要将类的“未知”成员的初始化委托给该类本身提供的另一个初始化器。

我调整了您的示例,以使用基本的init()作为协议的委托初始化程序来说明这一点。

如您所见,这要求您的类在调用init()时为所有成员实现初始值。在这种情况下,我通过在每个成员的声明中提供默认值来做到这一点。而且,由于某些成员并不总是有实际的初始值,因此我将其更改为自动展开可选对象。

为了使思考更有趣,您的类不能将初始化委派给协议提供的初始化程序,除非它是通过便捷初始化程序进行的。

我想知道所有这些限制是否值得解决。我怀疑您正在尝试使用协议,因为您需要在实现该协议的类之间一致地初始化一堆公共变量。也许使用委托类将提供比协议少花时间的解决方案(只是一个想法)。

protocol Thing:AnyObject
{
    var color:UIColor! { get set }
    init()
}

extension Thing 
{    
    init(color:UIColor)
    {  
       self.init()
       self.color = color
    }
}

class NamedThing:Thing 
{
    var name:String!   = nil
    var color:UIColor! = nil

    required init() {}

    convenience init(name:String,color:UIColor) 
    {
        self.init(color:color)
        self.name = name
    }
}
2020-07-07