协议扩展中的"自我"是什么?

Min*_*008 20 protocols swift swift-extensions swift-protocols

我看到了很多以下格式的例子

extension Protocolname where Self: UIViewController
Run Code Online (Sandbox Code Playgroud)

什么是where Self协议扩展.我找不到关于此的文档.

Bra*_*don 33

该语法为:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID521

考虑:

protocol Meh {
    func doSomething();
}

//Extend protocol Meh, where `Self` is of type `UIViewController`
//func blah() will only exist for classes that inherit `UIViewController`. 
//In fact, this entire extension only exists for `UIViewController` subclasses.

extension Meh where Self: UIViewController {
    func blah() {
        print("Blah");
    }

    func foo() {
        print("Foo");
    }
}

class Foo : UIViewController, Meh { //This compiles and since Foo is a `UIViewController` subclass, it has access to all of `Meh` extension functions and `Meh` itself. IE: `doSomething, blah, foo`.
    func doSomething() {
        print("Do Something");
    }
}

class Obj : NSObject, Meh { //While this compiles, it won't have access to any of `Meh` extension functions. It only has access to `Meh.doSomething()`.
    func doSomething() {
        print("Do Something");
    }
}
Run Code Online (Sandbox Code Playgroud)

以下将给出编译器错误,因为Obj无法访问Meh扩展函数.

let i = Obj();
i.blah();
Run Code Online (Sandbox Code Playgroud)

但是下面的方法会奏效.

let j = Foo();
j.blah();
Run Code Online (Sandbox Code Playgroud)

换句话说,Meh.blah()仅适用于类型的类UIViewController.

  • @菲利克斯;因为扩展实际上是该协议的扩展,而不是类本身的扩展......但只有在`UIViewController` 实现它时。 (2认同)

Hus*_*bir 5

这是一个示例,解释了self的用途:UIViewController

protocol SBIdentifiable {
    static var sbIdentifier: String { get }
}

extension SBIdentifiable where Self: UIViewController {
    static var sbIdentifier: String {
        return String(describing: self)
    }
}

extension UIVieWcontroller: SBIdentifiable { }

class ViewController: UIViewController {
  func loadView() {
  /*Below line we are using the sbIdentifier which will return the 
   ViewController class name.
    and same name we would mentioned inside ViewController 
    storyboard ID. So that we do not need to write the identifier everytime. 
   So here where Self: UIViewController means it will only conform the protocol of type UIViewController*/ 

  let viewController = self.instantiateViewController(withIdentifier: 
    self.sbIdentifier) as? SomeBiewController
  }
}
Run Code Online (Sandbox Code Playgroud)


boo*_*oog 5

您可以在此处找到相同的示例WWDC2015-408,(强烈建议观看?它说明了原因

而且,另一个类似的例子是带有通用 Where 子句的扩展

struct Stack<Element> {
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}
Run Code Online (Sandbox Code Playgroud)

where 子句对扩展增加了一个要求,这样扩展只在栈中的项是可相等的情况下才添加 isTop(_:) 方法。

extension Stack where Element: Equatable {
    func isTop(_ item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        return topItem == item
    }
}
Run Code Online (Sandbox Code Playgroud)