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

swift类和结构的扩展表现不同,swift,Swift,问题是,我有一些结构或类,具有符合某些协议的通用约束。当我试图根据泛型类型T的类型添加专门的实现时,它对类有效,但对结构无效。我不能在我的特定用例中使用类,因为这个类应该符合需要初始值设定项的协议,但我不能在扩展中指定类初始值设定项 有什么办法让它工作吗?还是我应该选择另一条路?下面是一个演示问题的代码片段 protocol ProtocolA {} protocol ProtocolB: ProtocolA {} protocol ProtocolC { fun act() } st

问题是,我有一些结构或类,具有符合某些协议的通用约束。当我试图根据泛型类型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()'"
协议协议{}
协议ProtocolB:ProtocolA{}
协议协议{
娱乐法
}
结构:ProtocolA{}
struct StructB:ProtocolB{}
struct StructC:ProtocolC{}
扩展结构{
func法案(){
打印(“一般”)
}
}
扩展结构c,其中T:ProtocolB{
func法案(){
打印(“特殊”)
}
}
C类:协议{
}
扩展类C{
func法案(){
打印(“一般”)
}
}
扩展类c,其中T:ProtocolB{
func法案(){
打印(“特殊”)
}
}
设classCA=ClassC()
设classCB=ClassC()
//这很有效
classCA.act()/->“一般”
classCB.act()/->“特殊”
设structCA=StructC()
设structCB=StructC()
//甚至不编译
structCA.act()
structCB.act()//错误:“对'act()'的使用不明确”
UPD:如果我使用类型为alias的协议和扩展协议而不是结构,那么它可以工作:

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"
ProtocolD协议{
别名V
func法案()
}
struct-StructD:ProtocolD{
类型别名V=T
}
伸展原冷{
func法案(){
打印(“一般”)
}
}
扩展ProtocolD,其中V:ProtocolB{
func法案(){
打印(“特殊”)
}
}
设structDA=StructD()
设structDB=StructD()
//又起作用了
structDA.act()/->“常规”
structDB.act()/->“特殊”
但它仍然不能解决或解释类和结构的不同行为问题


UPD:为该问题提交了雷达文件rdar://23314307 你错过了变异

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

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

`let structCB = StructC<StructB>()`
StructB
继承
ProtocolB
,但
ProtocolB
不“继承”
StructB
。 如果为该扩展设置默认实现,它将工作:

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

最后我理解了你的问题,也变得很感兴趣——为什么它不起作用。 问题是
协议ProtocolB:ProtocolA{}
然后在generic
ProtocolB
中,它不被视为继承自
ProtocolA
。我想你可以改变一下你的逻辑,解决这个问题:


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

@Pravan-不是struct上的每个方法都应该标记为“mutating”,并且它不必处理所描述的问题。@Pravan-如果不添加“mutating”,那么添加“mutating”会破坏
StructC
与协议
ProtocolC
的一致性
mutating
到协议本身。@IlyaPuchka当然不是每个方法都必须标记为
mutating
,但是,在这种情况下,您的扩展正在改变
self
。如果进行更改并运行示例代码,您将看到它已编译@Pravan-StructC方法“act”的哪些方面发生了变化?它不可编译。@Pranav您应该在回答中解释您提出此解决方案的原因。据我所知,当我在扩展中指定类型
T
的约束时,我说此扩展应该应用于符合此约束的任何类型的T。因此
StructB
符合
T:ProtocolB
,因为它符合
ProtocolB
,所以它应该从这个扩展中得到实现。这不对吗?另外,在我的实际用例中,我不能像你建议的那样在扩展中使用具体类。你能更详细地解释一下你的建议吗
ProtocolB
是否完全符合您的要求—在
ProtocolA
之上添加一些功能。举例来说,这并不重要。如果我在
StructB
中添加一些函数而不将它们添加到
ProtocolB
中,我将无法在扩展中访问它们,因为
T
ProtocolB
,而不是
StructB
。我希望它不会与所有这些A和B混淆太多……我也试着不从
ProtocolA
继承
ProtocolB
,而是在
StructB
中分别遵循它们,比如:
struct-StructB:ProtocolA,ProtocolB{/code>,但它仍然存在歧义错误。
extension StructC where T: StructB {
    func act() {
        print("special")
    }
}