Swift 如何将协议类型传递给泛型函数?

Swift 如何将协议类型传递给泛型函数?,swift,generics,swift-protocols,type-bounds,Swift,Generics,Swift Protocols,Type Bounds,我想根据类型(URL的一部分,如果您必须知道的话)创建字符串 考虑以下示例代码: import Foundation protocol TestP { var p: Int { get } } protocol TestQ: TestP { var q: Int { get } } struct TestR: TestQ { var p = 1 var q = 2 } func toDescription<T: TestP>(type: T.Ty

我想根据类型(URL的一部分,如果您必须知道的话)创建字符串

考虑以下示例代码:

import Foundation


protocol TestP {
    var p: Int { get }
}
protocol TestQ: TestP {
    var q: Int { get }
}
struct TestR: TestQ {
    var p = 1
    var q = 2
}

func toDescription<T: TestP>(type: T.Type) -> String {
    switch type {
        case is TestR.Type: return "Arrrr"
        default: return "unsupported"
    }
}
<代码>导入基础 协议测试{ var p:Int{get} } 协议TestQ:TestP{ var q:Int{get} } 结构TestR:TestQ{ var p=1 变量q=2 } func toDescription(类型:T.type)->字符串{ 开关类型{ 大小写为TestR。类型:返回“Arrrr” 默认值:返回“不支持” } } 这似乎相当不错;我不需要依赖不安全的度量(字符串),也不需要单独的枚举

让我们看一些用法示例:

func example1<T: TestP>(val: T) {
    print("Processing \(toDescription(type: T.self))")
}

func example2() {
    print("Processing \(toDescription(type: TestR.self))")
}

func example3() {
    print("Processing \(toDescription(type: TestQ.self))")
}
func示例1(val:T){
打印(“处理\(toDescription(类型:T.self)))
}
func示例2(){
打印(“处理\(toDescription(type:TestR.self)))
}
func示例3(){
打印(“处理\(toDescription(type:TestQ.self)))
}
虽然前两个函数很好(通用版本特别好!),但第三个函数不编译:

错误:在参数类型
TestQ.Protocol.type
中,
TestQ.Protocol
与预期类型
TestP

TestP.Type
TestP.Protocol
也不能用作参数

如何将协议类型传递给(通用)函数?

protocoltestp{
var p:Int{get}
}
协议TestQ:TestP{
var q:Int{get}
}
结构TestR:TestQ{
var p=1
变量q=2
}
结构测试:TestP
{
var p=42
}
func toDescription(类型:T.type)->字符串
{
开关类型
{
case let x,其中x==TestR.self:
返回“Arrr”
违约:
返回“不支持”
}
}
打印(toDescription(类型:TestR.self))//Arrr
打印(toDescription(type:TestS.self))//不支持

这不是出于正当理由编译的–比如说
TestP
有一个
static
要求。您可以从
到description
中调用
类型上的该需求,但是如果您能够通过
TestQ.self
,就不会有可调用的实现。这是更大限制的一部分(为了防止此类不安全情况,但在其他方面充满了完全安全的边缘情况),也就是说,你不能使用
TestQ
作为一个符合
TestP
@Hamish的类型。我想我希望能够编写
func f(type:T.Protocol)
,在这种情况下,编译器可以检查我没有调用协议类型上的静态成员。(好吧,即使在我编写的版本中,它也会阻止我访问静态成员,因为它可能会失败。)有趣的事实:如果你切换这样的参数
type
,模式
就是TestQ。type
不会引发“从不匹配”的警告。如果协议确实符合自身,那么是的,我会期望类似
func f的东西(type:T.Protocol)
开始工作(尽管它会禁止前两个示例工作)这并不能解决OP存在的问题。OP试图将
TestQ.self
传递到
toDescription(type:)
,但这会产生编译器错误。此外,由于缺乏解释,纯代码的答案很少提供更多细节。
protocol TestP {
    var p: Int { get }
}
protocol TestQ: TestP {
    var q: Int { get }
}
struct TestR: TestQ {
    var p = 1
    var q = 2
}

struct TestS: TestP
{
    var p = 42
}

func toDescription<T: TestP>(type: T.Type) -> String
{
    switch type
    {
    case let x where x == TestR.self:
        return "Arrr"
    default:
        return "Unsupported"
    }
}

print (toDescription(type: TestR.self)) // Arrr
print (toDescription(type: TestS.self)) // Unsupported