我有一个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
的泛型类型,但我无法找出为变量赋值声明泛型类型的语法。
答案 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)并没有这样做。鸭子打字是一种伪多态性。它不是真正的多态。