协议扩展中的 'where self' 是什么
what is 'where self' in protocol extension
我看到了很多格式如下的例子
extension Protocolname where Self: UIViewController
协议扩展中的where Self
是什么。我找不到这方面的文档。
考虑:
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
.
的 类
这里有一个例子解释了 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
}
}
你可以在这里找到相同的例子: 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
}
}
我看到了很多格式如下的例子
extension Protocolname where Self: UIViewController
协议扩展中的where Self
是什么。我找不到这方面的文档。
考虑:
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
.
这里有一个例子解释了 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
}
}
你可以在这里找到相同的例子: 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
}
}