2017-05-06 26 views
1

我有一个协议,看起来像这样的协议:可变符合具有通用功能

protocol MyProtocol { 
    associatedtype SpeedType 
    var name: String {get set} 
    func forward(_: SpeedType) 
} 

我做了2符合本协议的简单类:

class A: MyProtocol { 
    typealias SpeedType = Double 
    var name: String 

    init(name:String) { 
     self.name = name 
    } 

    func forward(_ s: Double) { 
     print("Moving \(s) km/h") 
    } 
} 

class B: MyProtocol { 
    typealias SpeedType = Int 
    var name: String 

    init(name:String) { 
     self.name = name 
    } 

    func forward(_ s: Int) { 
     print("Moving \(s) km/h") 
    } 
} 

我想要实现的是能够声明类型的变量MyProtocol,并在稍后将其初始化为:

let x: Bool = true 
var person: MyProtocol 
if x { 
    person = A(name: "Robot") 
} else { 
    person = B(name: "Human") 
} 

之前我做了转发()方法“通用”我能够做到这一点,但现在我得到下一个错误: 协议“MyProtocol”只能用作通用约束,因为它具有Self或关联类型要求。

所以我的目标是有一个方法forward()方法,可以采取为我指定类型的参数的参数,也可以申报符合我的协议类型的变量。

+1

的可能的复制[协议只能被用作通用约束,因为它有自或associatedType要求(http://stackoverflow.com/questions/36348061/protocol-can-only-be-used- as-a-generic-constraint-because-it-has-self-or-associa) –

回答

5

斯威夫特不允许这样做。

原因如下:你不知道有什么关于person.forward(_:)参数的类型。没有办法调用它。 MyProtocol本质上定义了一组开放式的独立类型。

如果你不希望能够调用person.forward(_:),而你只是希望能够访问非通用person.name属性,然后分裂的协议为基础,非通用协议定义name,和子协议增加了通用的forward(_:)方法。

protocol NamedThing { 
    var name: String {get set} 
} 

protocol MovableNamedThing: NamedThing { 
    associatedtype SpeedType 
    func forward(_: SpeedType) 
} 

class A: MovableNamedThing { 
    typealias SpeedType = Double 
    var name: String 

    init(name:String) { 
     self.name = name 
    } 

    func forward(_ s: Double) { 
     print("Moving \(s) km/h") 
    } 
} 

class B: MovableNamedThing { 
    typealias SpeedType = Int 
    var name: String 

    init(name:String) { 
     self.name = name 
    } 

    func forward(_ s: Int) { 
     print("Moving \(s) km/h") 
    } 
} 

let x: Bool = true 
var person: NamedThing 
if x { 
    person = A(name: "Robot") 
} else { 
    person = B(name: "Human") 
} 
+0

谢谢,这是有效的。有趣的解决方案,我甚至没有想过。 – Alex

+0

有没有什么办法可以在一个人变量上调用forward(_ :)方法? – Alex

+0

不,我在答复的第二段已经回答了这个问题。我不知道如何更清楚地说出来。 –