Swift 具有泛型和专门化的协议

Swift 具有泛型和专门化的协议,swift,generics,swift-protocols,Swift,Generics,Swift Protocols,是否有办法在协议中定义通用函数,并允许一致性对象定义该协议的专门化?例如: protocol Generic { func generic<T>(prop: T, otherProp: String) } class Gen: Generic { func generic<T>(prop: T, otherProp: String) { print("generic") } func generic(prop: Stri

是否有办法在协议中定义通用函数,并允许一致性对象定义该协议的专门化?例如:

protocol Generic {
    func generic<T>(prop: T, otherProp: String)
}

class Gen: Generic {
    func generic<T>(prop: T, otherProp: String) {
        print("generic")
    }

    func generic(prop: String, otherProp: String) {
        print(prop)
    }
}
我得到了以下预期结果:

generic
Hello
但是,如果我声明
inst
类型为
Generic

let inst: Generic = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")
我得到:

generic
generic

因此,如果我有一个类型为
Generic
的属性,我就无法使用协议实现者提供的泛型函数的专门化。这是预期的行为吗?是否有一种方法可以实现我想要的行为,即即使通过协议接口访问,也可以使用通用函数的专门化?我希望你能深入了解这一点。谢谢大家。

如果您将协议要求声明为通用函数,则无法通过协议类型调用同一函数的更专业的重载版本。但是,您可以通过检查泛型输入参数的类型,专门为您的类实现泛型函数

class Gen: Generic {
    func generic<T>(prop: T, otherProp: String) {
        if prop is String {
            print(prop)
        } else {
            print("generic")
        }
    }
}

let inst: Generic = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")
class-Gen:Generic{
func泛型(prop:T,otherProp:String){
如果道具是字符串{
印刷品(道具)
}否则{
打印(“通用”)
}
}
}
let inst:Generic=Gen()
仪器通用(道具:1,其他道具:“Go”)
指令通用(道具:“你好”,其他道具:“停止”)

您可以在协议中添加方法签名
generic(String,String)
,并添加带有扩展名的默认实现:

protocol Generic {
    func generic<T>(prop: T, otherProp: String)
    func generic(prop: String, otherProp: String)
}

extension Generic {
    func generic(prop: String, otherProp: String) {
        generic(prop: prop as Any, otherProp: otherProp)
    }
}
协议通用{
func泛型(prop:T,otherProp:String)
func-generic(prop:String,otherProp:String)
}
扩展泛型{
func-generic(prop:String,otherProp:String){
通用(道具:道具与任何道具相同,其他道具:其他道具)
}
}

Phelippe有答案,但我会非常小心。只有当您能够提供性能改进时,才应该使用它。如果这些实现有不同的行为,那么这是一个非常脆弱且难以调试的过程,并且规则可能非常微妙(例如,如果调用不同的泛型方法,然后调用它,则可能会丢失专门化)。基本上,如果您有
f(value:T)
f(value:String)
,则它们对于String应该具有相同的可见行为;后者可能更有效。我考虑了一个类似的解决方案,但我看到这个解决方案的一个大问题是,为了给符合协议的类型添加专门化,我必须修改协议。如果我没有能力修改协议,这将不起作用。一般来说,我认为修改接口以适应特定的实现是不好的做法。不过,谢谢你的建议。最后我就是这么做的。我想我是希望我错过了什么,或者有人能明确告诉我这是预期的行为。我想我可能会尝试在swift项目中创建一个问题,看看是否可以添加我正在寻找的功能。不过,谢谢你的回答。即使在技术上可行,我也不认为这个功能会或应该实现。在一致性类中重载协议需求不应导致在通过协议类型访问时调用重载版本,因为重载版本不会在协议本身上声明。如果在示例中将case
inst
转换为
Gen
,则可以直接调用重载版本。
protocol Generic {
    func generic<T>(prop: T, otherProp: String)
    func generic(prop: String, otherProp: String)
}

extension Generic {
    func generic(prop: String, otherProp: String) {
        generic(prop: prop as Any, otherProp: otherProp)
    }
}