【问题标题】:what is 'where self' in protocol extension协议扩展中的“where self”是什么
【发布时间】:2017-09-02 22:14:24
【问题描述】:

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

extension Protocolname where Self: UIViewController

协议扩展中的where Self 是什么。我找不到这方面的文档。

【问题讨论】:

    标签: swift protocols swift-protocols swift-extensions


    【解决方案1】:

    该语法是: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 类型的类。

    【讨论】:

    • 为什么人们对protocol Mehextension Meh where Self: UIViewController使用相同的名称Meh,这让我很困惑。
    • @Felix;因为扩展实际上是该协议的扩展,而不是类本身的扩展......但只有当 UIViewController 实现它时。
    • 如果我想写一个通用的 Meh() 和一个只能用它执行的 Meh() 是一个 ViewController 对象怎么办?
    【解决方案2】:

    这里有一个例子解释了 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
      }
    }
    

    【讨论】:

      【解决方案3】:

      你可以在这里找到同样的例子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子句给扩展增加了一个需求,使得扩展只在栈中的item相等时才添加isTop(_:)方法。

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

      【讨论】:

        猜你喜欢
        • 2017-04-24
        • 1970-01-01
        • 2016-07-29
        • 1970-01-01
        • 2021-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多