Last active
March 15, 2016 01:14
-
-
Save jeamesbone/fbc36b8b2c9526e9ec94 to your computer and use it in GitHub Desktop.
Swift Struct Composition
This file contains 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
// Value types are awesome, but we lose the ability to inherit functionality if we use structs in swift. | |
// | |
// Below are some experiments where I've been playing with composition to solve this for a common use case | |
// where we want to have some common base model fields. | |
import Foundation | |
// Create a struct to hold our common fields | |
struct CommonFields { | |
let id: Int | |
init(dictionary: [String: AnyObject]) { | |
id = dictionary["id"] as! Int | |
} | |
} | |
// Our 'child' model | |
struct User { | |
let common: CommonFields | |
let name: String | |
init(dictionary: [String: AnyObject]) { | |
// Utilise common initialisation | |
common = CommonFields(dictionary: dictionary) | |
name = dictionary["name"] as! String | |
} | |
} | |
// Create user | |
let user = User(dictionary: ["id": 5, "name": "john testington"]) | |
user.common.id // 5 | |
===================================================================== | |
// How about if we want some polymorphism? | |
protocol BaseModel { | |
var common: CommonFields { get } | |
} | |
// Identical to before but with protocol conformance | |
struct User: BaseModel { | |
let common: CommonFields | |
let name: String | |
init(dictionary: [String: AnyObject]) { | |
common = CommonFields(dictionary: dictionary) | |
name = dictionary["name"] as! String | |
} | |
} | |
let someModel: BaseModel = User(dictionary: ["id": 5, "name": "john testington"]) | |
someModel.common.id // 5 | |
===================================================================== | |
// Protocol extensions for convenience | |
protocol BaseModel { | |
var common: CommonFields { get } | |
var id: Int | |
} | |
extension BaseModel { | |
var id: Int { | |
return common.id | |
} | |
} | |
// User as before | |
let user = User(dictionary: ["id": 5, "name": "john testington"]) | |
user.id // 5 | |
// There are a few issues with this | |
// 1. Our 'common' struct is exposed as public (we can't make protocol vars private) | |
// 2. If we add a field to our common fields we need to add a corresponding field to | |
// the protocol if we want the convenient getter |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment