2017-02-28 85 views
0

我想根据类型创建字符串(如果您必须知道的话,部分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" 
    } 
} 

这似乎相当不错;我不需要依赖不安全的措施(字符串),也不需要单独的枚举。

让我们看看一些使用例如:

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))") 
} 

虽然前两个功能都很好(通用版特别好听!),第三不编译:

Error: in argument type TestQ.Protocol.Type , TestQ.Protocol does not conform to expected type TestP

TestP.TypeTestP.Protocol也不作为参数工作。

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

+1

这并不是很好的理由 - 比如'TestP'有一个'static'要求。你可以在'toDescription'中调用'type'的要求 - 但是如果你能够通过'TestQ.self',那么就没有实现可以调用。 – Hamish

+0

这是一个更大限制的一部分(为了防止这些不安全的情况,但是否则充满了完全安全的边缘情况),这就是[协议不符合自己](http:// stackoverflow .com/questions/33112559/protocol-doesnt-conform-to-itself) - 所以你不能使用'TestQ'作为符合'TestP'的类型。 – Hamish

+0

@Hamish我明白了。我想我希望能写'func f (type:T.Protocol)',那么在这种情况下,编译器可以检查我没有在协议类型上调用静态成员。 (好吧,即使在我编写的版本中,它也可能阻止我访问静态成员,因为它可能会失败。) – Raphael

回答

-2
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 
+1

这没有解决OP所具有的问题。 OP正试图将'TestQ.self'传递给'toDescription(type:)',但它会产生编译器错误。 – Hamish

+2

此外,仅有代码的答案很少提供很多洞见,因为缺乏解释。 – Raphael

相关问题