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