//: Playground - noun: a place where people can play import Cocoa class Observation: Hashable { var hashValue: Int { return ObjectIdentifier(self).hashValue } static func ==(lhs: Observation, rhs: Observation) -> Bool { return lhs === rhs } let observer: (T) -> () init(observer: @escaping (T) -> ()) { self.observer = observer } } class Observable { var value: T { didSet { for observation in observations { observation.observer(value) } } } private var observations: Set> = [] init(value: T) { self.value = value } func observe(_ keyPath: KeyPath, callback: @escaping (U) -> ()) -> (() -> ()) { observations.insert(Observation { callback($0[keyPath: keyPath]) }) return {} } } struct User { let name: String let age: Int } let observableUser = Observable(value: User(name: "Jonh", age: 35)) let nameObservation = observableUser.observe(\.name) { name in print("New name:", name) } let ageObservation = observableUser.observe(\.age) { age in print("New age:", age) } observableUser.value = User(name: "Dow", age: 40)