Last active
July 12, 2017 09:08
-
-
Save towry/b41f1f0a6d48149a712186045806c9b8 to your computer and use it in GitHub Desktop.
swift proxy pattern demo.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// https://medium.com/@jegnux/safe-collection-subsripting-in-swift-3771f16f883 | |
// https://github.com/ReactiveX/RxSwift/issues/826 | |
// | |
import Foundation | |
// we define a fire protocol. | |
protocol FireProtocol { | |
// Type placeholder | |
associatedtype FireType | |
var fire: FireType { get } | |
} | |
// make a fire type. | |
public class Fire<Base> { | |
public let base: Base | |
public init(_ base: Base) { | |
// base is the conforming type that conform to FireProtocol, | |
// in current file. | |
self.base = base | |
} | |
// default behavior | |
func fireInTheHole() { | |
print("fire !!!!!") | |
} | |
} | |
extension FireProtocol { | |
// Self reference to the conforming type. | |
public var fire: Fire<Self> { | |
get { | |
return Fire(self) | |
} | |
} | |
} | |
// ------------------------------- | |
// Begin the fun part | |
// Create a dragon. | |
public class Dragon {} | |
// give the dragon fire attribute. | |
extension Dragon: FireProtocol {} | |
// Instead of extension the Dragon class, we extension `Fire` class | |
// and give the dragon a property that is a `Fire`. then the dragon can have the | |
// ability that Fire object have. | |
let dragon = Dragon() | |
dragon.fire.fireInTheHole() | |
extension Fire { | |
public func fireAgain() { | |
print("fireAgain") | |
} | |
} | |
// See ? | |
dragon.fire.fireAgain() | |
// create another type. | |
public class Bird: FireProtocol {} | |
// bird also have the ability that dragon have. | |
let bird = Bird() | |
bird.fire.fireInTheHole() | |
bird.fire.fireAgain() | |
// This is nothing special to the normal protocol oriented programming way. | |
// We can use generic constraint to add ability to one type. | |
// add ability to dragon only. | |
extension Fire where Base: Dragon { | |
public func dragonOnlyMethod() { | |
print("dragon only method") | |
} | |
} | |
dragon.fire.dragonOnlyMethod() | |
// error: 'Bird' is not a subtype of 'Dragon' | |
// bird.fire.dragonOnlyMethod() | |
extension Fire where Base: Bird { | |
public func eatWorm() { | |
print("bird eat worm") | |
} | |
} | |
bird.fire.eatWorm() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment