加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift2 – 如何在协议扩展中定义初始化程序?

发布时间:2020-12-14 05:56:53 所属栏目:百科 来源:网络整理
导读:protocol Car { var wheels : Int { get set} init(wheels: Int)}extension Car { init(wheels: Int) { self.wheels = wheels }} on self.wheelels = wheel我得到错误 Error: variable 'self' passed by reference before being initialized 如何在协议扩展
protocol Car {
     var wheels : Int { get set}

     init(wheels: Int)

}

extension Car {
    init(wheels: Int) {
        self.wheels = wheels
    }
}

on self.wheelels = wheel我得到错误

Error: variable 'self' passed by reference before being initialized

如何在协议扩展中定义初始化程序?

正如您可以看到,这在这些情况下不起作用,因为编译必须确保在使用struct / enum / class之前初始化所有属性。

您可以使另一个初始化程序成为一个要求,因此编译器知道所有属性都已初始化:

protocol Car {
    var wheels : Int { get set }
    // make another initializer
    // (which you probably don't want to provide a default implementation)
    // a protocol requirement. Care about recursive initializer calls :)
    init()
    init(wheels: Int)

}

extension Car {
    // now you can provide a default implementation
    init(wheels: Int) {
        self.init()
        self.wheels = wheels
    }
}

// example usage

// mark as final
final class HoverCar: Car {
    var wheels = 0
    init() {}
}

let drivableHoverCar = HoverCar(wheels: 4)
drivableHoverCar.wheels // 6

从Xcode 7.3 beta 1开始,它可以像预期一样使用结构体,但不适用于类,因为如果它们不是最终的,那么协议中的init(wheels:Int)就是一个必需的init,它可以被覆盖,因此不能通过扩展来添加。解决方法(按照编译器的建议):使课程最终化。

另一种解决办法(深入;没有最后的班级)

要使用类而不使它们成为最终,您还可以在协议中删除init(wheels:Int)要求。看来它的行为与以前没有什么不同,但考虑这个代码:

protocol Car {
    var wheels : Int { get set }
    init()
    // there is no   init(wheels: Int)
}

extension Car {
    init(wheels: Int) {
        self.init()
        print("Extension")
        self.wheels = wheels
    }
}

class HoverCar: Car {
    var wheels = 0
    required init() {}
    init(wheels: Int) {
        print("HoverCar")
        self.wheels = wheels
    }
}

// prints "HoverCar"
let drivableHoverCar = HoverCar(wheels: 4)

func makeNewCarFromCar<T: Car>(car: T) -> T {
    return T(wheels: car.wheels)
}

// prints "Extension"
makeNewCarFromCar(drivableHoverCar)

因此,如果您从通用上下文中创建一个Car,其中调用init的类型仅被称为Car即使在HoverCar中定义了初始化程序,也会调用扩展初始化程序。这只是因为在协议中没有init(wheels:Int)要求。

如果添加它,则将前一个问题声明为final,但现在打印两次“HoverCar”。无论哪种方式,第二个问题可能永远不会发生,所以它可能是一个更好的解决方案

Sidenote:如果我犯了一些错误(代码,语言,语法,…),欢迎纠正我:)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读