swift类和结构的扩展表现不同

时间:2015-10-29 10:34:35

标签: swift

问题是我有一些结构或类具有符合某些协议的泛型约束。当我尝试根据泛型类型T的类型添加专门的实现时,它适用于类但不适用于结构。我不能在我的特定用例中使用类,因为这个类应该符合需要初始化程序的协议,但我不能在扩展中指定类初始化程序。

任何使其有效的方法?或者我应该选择其他路径?这是一个演示问题的代码段。

protocol ProtocolA {}
protocol ProtocolB: ProtocolA {}
protocol ProtocolC {
    fun act()
}

struct StructA: ProtocolA {}

struct StructB: ProtocolB {}

struct StructC<T: ProtocolA>: ProtocolC {}

extension StructC {
    func act() {
        print("general")
    }
}

extension StructC where T: ProtocolB {
    func act() {
        print("special")
    }
}

class ClassC<T: ProtocolA>: ProtocolC {
}

extension ClassC {
    func act() {
        print("general")
    }
}

extension ClassC where T: ProtocolB {
    func act() {
        print("special")
    }
}

let classCA = ClassC<StructA>()
let classCB = ClassC<StructB>()

//this works
classCA.act() //-> "general"
classCB.act() //-> "special"

let structCA = StructC<StructA>()
let structCB = StructC<StructB>()

//Does not even compile
structCA.act() 
structCB.act() // error: "Ambigous use of 'act()'"

UPD:如果我使用带有别名的协议并扩展协议而不是struct,那么它可以工作:

protocol ProtocolD {
    typealias V
    func act()
}

struct StructD<T: ProtocolA>: ProtocolD {
    typealias V = T
}

extension ProtocolD {
    func act() {
        print("general")
    }
}

extension ProtocolD where V: ProtocolB {
    func act() {
        print("special")
    }
}

let structDA = StructD<StructA>()
let structDB = StructD<StructB>()

//works again
structDA.act() //-> "general"
structDB.act() //-> "special"

但它仍然无法解决或解释类和结构的不同行为问题。

UPD:提交该问题的雷达rdar:// 23314307

2 个答案:

答案 0 :(得分:0)

从第一眼看到你在这里宣布

`let structCB = StructC<StructB>()`

但是当StructB仅继承此协议时,使用ProtocolB实现扩展:

extension StructC where T: ProtocolB {
    func act() {
        print("special")
    }
}

StructB继承ProtocolB,但ProtocolB没有&#34;继承&#34; StructB。 如果您为此扩展程序进行默认实现,它将起作用:

extension StructC where T: StructB {
    func act() {
        print("special")
    }
}

UPD:

最后我理解了你的问题并且也对此感兴趣 - 为什么它不起作用。 问题是protocol ProtocolB: ProtocolA {} 然后,通用ProtocolB不被视为来自ProtocolA的继承。我认为你可以改变一点逻辑并解决问题:

您的ProtocolB扩展了ProtocolA,例如添加了一些功能。如果可以接受,您可以在StructB中添加功能

答案 1 :(得分:-1)

你错过了mutating

extension StructC where T: ProtocolB {
    mutating func act() {
        print("special")
    }
}