问题是我有一些具有符合某些协议的泛型约束的结构或类。当我尝试根据泛型类型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:如果我使用protocol with type alias和extend protocol而不是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

最佳答案

从第一眼看到你在这里申报

`let structCB = StructC<StructB>()`

但是,当StructB只继承此协议时,使用ProtocolB实现扩展:
extension StructC where T: ProtocolB {
    func act() {
        print("special")
    }
}

StructB继承ProtocolB,但ProtocolB不“继承”StructB
如果将此扩展设置为默认实现,则它将工作:
extension StructC where T: StructB {
    func act() {
        print("special")
    }
}

升级版:
最后我明白了你的问题,也变得很感兴趣——为什么它不起作用。
问题是protocol ProtocolB: ProtocolA {}
然后在泛型中ProtocolB不被视为来自ProtocolA的继承。我想你可以改变一下你的逻辑来解决这个问题:
您的ProtocolB通过添加一些函数来扩展ProtocolA。如果可以接受,可以在StructB中添加函数

10-01 22:44