在Swift中,类型(非实例)是否符合协议?

时间:2015-08-29 21:53:47

标签: swift generics types polymorphism

我有一个ViewController,它使用来自我控制之外的框架的类(称为A)。 A提供了我需要的类函数(称之为f)。我想让A很容易在测试中模拟出来。

所以我的想法是创建一个与P具有相同签名的协议A,扩展A以实现P,然后创建一个也实现M的模拟类P 1}}并且具有f的虚拟实现。然后在我的测试中,我可以做viewController.dependency = M,一切都应该是花花公子。

这说起来容易做起来难,因为我希望你能帮助我理解。

在我的viewController中,很容易声明一个包含符合协议的实例的变量,然后将该变量重新分配给另一个符合协议的实例:

// works
var dependency: P = A()
dependency.f()
dependency = M()
dependency.f()

但仅使用类型来做同样的事情并不起作用:

// doesn't work
var dependency = A.self
dependency = M.self  // cannot assign value of M.Type to a value of type A.Type

// also doesn't work
var dependency: P = A.self // type A.Type does not conform to protocol P

有没有办法让这项工作?我想也许我可以使用dependency的泛型类型,但我无法找出为变量赋值声明泛型类型的语法。

2 个答案:

答案 0 :(得分:3)

如果您确实要存储类型本身,可以使用P.Type。以下适用于Swift 2:

protocol P {
    static func foo()
}

class A: P {
    static func foo() { print("A foo") }
}
class M: P {
    static func foo() { print("M foo") }
}

var dependency: P.Type = A.self
dependency = M.self

dependency.foo()

答案 1 :(得分:0)

它不起作用,因为当您说var dependency = A.self时,编译器会从右侧推断出dependency的类型为A。这意味着如果dependency被重新分配,则只能将其分配给A类类型的其他实例。当您使用与P相同的签名创建协议A,然后实现M的一个类P时,您仍然没有(并且可以&#t; t ,因为它超出您的控制范围,使 A 实施协议P。 Swift和Objective-C运行时的工作方式是每个对象都包含一个指向 type 类的指针。在分配时检查此类型,如果将右侧值分配给左侧声明,则右侧值必须在其继承层次结构中的某处具有左侧类型。

某些语言(例如Ruby)具有所谓的 duck typing ,如果对象或类像鸭子一样走,那么一只鸭子,即使它不是真的鸭子的一个实例。这就是你在这里寻找的东西,但是Swift(和Objective-C)并没有这样做。鸭子打字是一种伪多态性。它不是真正的多态。