web-dev-qa-db-ja.com

プロトコル拡張の「where self」とは

私は以下の形式で非常に多くの例を見てきました

extension Protocolname where Self: UIViewController

とは where Selfプロトコル拡張。これに関するドキュメントが見つかりませんでした。

19
Mini2008

その構文は: 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");
    }
}
_

ObjにはMeh拡張関数へのアクセス権がないため、次のコードではコンパイラエラーが発生します。

_let i = Obj();
i.blah();
_

しかし、以下は機能します。

_let j = Foo();
j.blah();
_

つまり、Meh.blah()UIViewController型のクラスでのみ使用できます。

32
Brandon

Where 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
  }
}
5
Hussain Shabbir

同じ例をこちらで見つけることができますWWDC2015-408 、(強くお勧めします、それは理由を示しています

また、別の同様の例は、一般的なWhere節を含む拡張機能です

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

Where句は拡張機能に要件を追加するため、拡張機能は、スタック内のアイテムが赤道である場合にのみisTop(_ :)メソッドを追加します。

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