Forked from AliSoftware/struct_vs_inheritance.swift
Last active
September 28, 2015 20:34
-
-
Save LukeDefeo/18add3fa16bdcb1ac618 to your computer and use it in GitHub Desktop.
Swift-Struct-Inheritance
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
// #!Swift-. | |
import Foundation | |
// MARK: - () classes | |
// Solution 1: | |
// - Use classes instead of struct | |
// Issue: Violate the concept of moving model to the value layer | |
// http://realm.io/news/andy-matuschak-controlling-complexity/ | |
typealias JSONDict = [NSObject:AnyObject] | |
class Vehicle { | |
let model: String | |
let color: String | |
init(jsonDict: JSONDict) { | |
model = jsonDict["model"] as String | |
color = jsonDict["color"] as String | |
} | |
} | |
class Car : Vehicle { | |
let horsepower: Double | |
let license_plate: String | |
override init(jsonDict: JSONDict) { | |
super.init(jsonDict: jsonDict) | |
horsepower = jsonDict["horsepower"] as Double | |
license_plate = jsonDict["license_plate"] as String | |
} | |
} | |
class Bicycle : Vehicle { | |
let chainrings: Int | |
let sprockets: Int | |
override init(jsonDict: JSONDict) { | |
super.init(jsonDict: jsonDict) | |
chainrings = jsonDict["chainrings"] as Int | |
sprockets = jsonDict["sprockets"] as Int | |
} | |
} | |
// MARK: - () struct + composition | |
// Solution 2: | |
// - keep value types | |
// - use composition. | |
// Issue: We violate the encapsulation principle, exposing the internal composition to the outside world | |
struct Vehicle { | |
let model: String | |
let color: String | |
init(jsonDict: JSONDict) { | |
model = jsonDict["model"] as String | |
color = jsonDict["color"] as String | |
} | |
} | |
struct Car { | |
let vehicle: Vehicle | |
let horsepower: Double | |
let license_plate: String | |
init(jsonDict: JSONDict) { | |
vehicle = Vehicle(jsonDict: jsonDict) | |
horsepower = jsonDict["horsepower"] as Double | |
license_plate = jsonDict["license_plate"] as String | |
} | |
} | |
struct Bicycle { | |
let vehicle: Vehicle | |
let chainrings: Int | |
let sprockets: Int | |
init(jsonDict: JSONDict) { | |
vehicle = Vehicle(jsonDict: jsonDict) | |
chainrings = jsonDict["chainrings"] as Int | |
sprockets = jsonDict["sprockets"] as Int | |
} | |
} | |
// MARK: - () struct, protocol + composition for parsing | |
// Solution : | |
// - keep value types, use a protocol | |
// - use intermediate struct only for parsing to keep encapsulation | |
// Issue: None… except code verbosity | |
protocol Vehicle { | |
var model: String { get } | |
var color: String { get } | |
} | |
private struct VehicleFields : Vehicle { | |
let model: String | |
let color: String | |
init(jsonDict: JSONDict) { | |
model = jsonDict["model"] as String | |
color = jsonDict["color"] as String | |
} | |
} | |
struct Car : Vehicle { | |
let model: String | |
let color: String | |
let horsepower: Double | |
let license_plate: String | |
init(jsonDict: JSONDict) { | |
let vehicle = VehicleFields(jsonDict: jsonDict) | |
model = vehicle.model | |
color = vehicle.color | |
horsepower = jsonDict["horsepower"] as Double | |
license_plate = jsonDict["license_plate"] as String | |
} | |
} | |
struct Bicycle : Vehicle { | |
let model: String | |
let color: String | |
let chainrings: Int | |
let sprockets: Int | |
init(jsonDict: JSONDict) { | |
let vehicle = VehicleFields(jsonDict: jsonDict) | |
model = vehicle.model | |
color = vehicle.color | |
chainrings = jsonDict["chainrings"] as Int | |
sprockets = jsonDict["sprockets"] as Int | |
} | |
} | |
// MARK: - () struct, protocols + global function for parsing | |
// Solution : [Does not compile] | |
// - keep value types, use a protocol | |
// - use a global function to fill the objects's fields conforming to the protocol | |
// Issue: does not work (it seems we can't pass 'self' as inout in the init() method) | |
// exposes the setter in the protocol and the structs anyway (so bad access protection) | |
protocol Vehicle { | |
var model: String { get set } | |
var color: String { get set } | |
} | |
private func parseVehicleFields(inout obj: Vehicle, jsonDict: JSONDict) { | |
obj.model = jsonDict["model"] as String | |
obj.color = jsonDict["color"] as String | |
} | |
struct Car : Vehicle { | |
var model: String | |
var color: String | |
let horsepower: Double | |
let license_plate: String | |
init(jsonDict: JSONDict) { | |
parseVehicleFields(&self, jsonDict) // Error: Car is not identical to Vehicle | |
horsepower = jsonDict["horsepower"] as Double | |
license_plate = jsonDict["license_plate"] as String | |
} | |
} | |
struct Bicycle : Vehicle { | |
var model: String | |
var color: String | |
let chainrings: Int | |
let sprockets: Int | |
init(jsonDict: JSONDict) { | |
parseVehicleFields(&self, jsonDict) // Error: Bicycle is not identical to Vehicle | |
chainrings = jsonDict["chainrings"] as Int | |
sprockets = jsonDict["sprockets"] as Int | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment