我有以下代码:
import UIKit protocol Fooable: class where Self: UIViewController { func foo() } class SampleViewController: UIViewController,Fooable { func foo() { print("foo") } } let vc1: Fooable = SampleViewController() let vc2: Fooable = SampleViewController() // vc1.show(vc2,sender: nil) - error: Value of type 'Fooable' has no member 'show' // (vc1 as! UIViewController).show(vc2,sender: nil) - error: Cannot convert value of type 'Fooable' to expected argument type 'UIViewController' (vc1 as! UIViewController).show((vc2 as! UIViewController),sender: nil)
注释行不编译.
为什么我被迫将协议类型对象强制转换为UIViewController,即使Fooable协议需要,符合它的类型是否继承自UIViewController?
采用协议Fooable告诉编译器这个特定的UIViewController响应foo(),不能再多了.
原文链接:https://www.f2er.com/swift/319456.html反之,Fooable不一定成为UIViewController.
约束Self:UIViewController只是编译器在编译时抱怨的另一个信息,如果受影响的类不是UIViewController
在您将SampleViewController注释为Fooable的情况下,编译器只知道SampleViewController响应foo().它不知道该类型实际上是UIViewController的子类.
因此,如果要访问具体类的属性,请不要为协议注释具体类.
protocol Fooable: class where Self: UIViewController { func foo() func show(_ vc: Fooable,sender: Any?) }
那么你可以使用Fooable,因为编译器知道采用协议的类型会响应方法.
将类型注释为协议的合适做法是,例如,当您要创建异构但受限制的集合类型时
let array : [CustomStringConvertible] = ["Foo",1,false] array.forEach{ print("\($0)")}
代码使用所有项目响应的description属性打印三个项目.编译器将这三个项识别为具有description属性的类型,而不是String,Int和Bool.