一尘不染

即使协议要求给定类型,也必须强制转换

swift

我有以下代码:

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


阅读 250

收藏
2020-07-07

共1个答案

一尘不染

采用该协议Fooable告诉编译器此特定UIViewController响应foo(),至少不会更多。

在相反的结论,Fooable没有 成为UIViewController必然。

如果受影响的类不是,约束Self: UIViewController只是编译器 在编译时 抱怨的另一信息。UIViewController

在您的情况下SampleViewControllerFooable对编译器进行批注仅知道SampleViewController对作出响应foo()。它不知道类型实际上是的子类UIViewController

因此,如果要访问具体类的属性,请不要在协议中为具体类注释。

但是,您可以将show方法和其他常见属性/方法添加到协议中

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财产,还不如StringIntBool

更新:

在Swift 5中,实现了对超类约束协议的支​​持。

2020-07-07