Skip to content

Instantly share code, notes, and snippets.

@LukeDefeo
Forked from AliSoftware/struct_vs_inheritance.swift
Last active September 28, 2015 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LukeDefeo/18add3fa16bdcb1ac618 to your computer and use it in GitHub Desktop.
Save LukeDefeo/18add3fa16bdcb1ac618 to your computer and use it in GitHub Desktop.
Swift-Struct-Inheritance
// #!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