Skip to content

Instantly share code, notes, and snippets.

@jeamesbone
Last active March 15, 2016 01:14
Show Gist options
  • Save jeamesbone/fbc36b8b2c9526e9ec94 to your computer and use it in GitHub Desktop.
Save jeamesbone/fbc36b8b2c9526e9ec94 to your computer and use it in GitHub Desktop.
Swift Struct Composition
// 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