web-dev-qa-db-de.com

Was ist "wo selbst" in der Protokollerweiterung

Ich habe so viele Beispiele mit folgendem Format gesehen

extension Protocolname where Self: UIViewController

Was ist where Self in der Protokollerweiterung. Ich konnte die Dokumentation dazu nicht finden.

19
Mini2008

Diese Syntax lautet: https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//Apple_ref/doc/uid/TP40014097-CH25-ID521

Erwägen:

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");
    }
}

Das Folgende gibt einen Compiler-Fehler aus, da Obj keinen Zugriff auf die Meh-Erweiterungsfunktionen hat.

let i = Obj();
i.blah();

Aber das Folgende wird funktionieren.

let j = Foo();
j.blah();

Mit anderen Worten, Meh.blah() ist nur für Klassen vom Typ UIViewController verfügbar.

32
Brandon

Hier ist ein Beispiel, das erklärt, wofür where self verwendet wird: 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
  }
}
5
Hussain Shabbir

Das gleiche Beispiel finden Sie hier : WWDC2015-408 , ( Es wird dringend empfohlen, es sich anzusehen , es wird illustriert der Grund)

Ein weiteres ähnliches Beispiel sind Erweiterungen mit einer generischen Where-Klausel

struct Stack<Element> {
    var items = [Element]()
    mutating func Push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

Die where-Klausel fügt der Erweiterung eine Anforderung hinzu, sodass die Erweiterung die isTop (_ :) -Methode nur hinzufügt, wenn die Elemente im Stapel gleichwertig sind.

extension Stack where Element: Equatable {
    func isTop(_ item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        return topItem == item
    }
}
2
boog