Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save GE-N/ce31231a285c65ff887f to your computer and use it in GitHub Desktop.
Save GE-N/ce31231a285c65ff887f to your computer and use it in GitHub Desktop.
Swift-Struct-Inheritance
// #!Swift-1.1
import Foundation
// MARK: - (1) 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 Vehicle1 {
let model: String
let color: String
init(jsonDict: JSONDict) {
model = jsonDict["model"] as String
color = jsonDict["color"] as String
}
}
class Car1 : Vehicle1 {
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 Bicycle1 : Vehicle1 {
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: - (2) struct + composition
// Solution 2:
// - keep value types
// - use composition.
// Issue: We violate the encapsulation principle, exposing the internal composition to the outside world
struct Vehicle2 {
let model: String
let color: String
init(jsonDict: JSONDict) {
model = jsonDict["model"] as String
color = jsonDict["color"] as String
}
}
struct Car2 {
let vehicle: Vehicle2
let horsepower: Double
let license_plate: String
init(jsonDict: JSONDict) {
vehicle = Vehicle2(jsonDict: jsonDict)
horsepower = jsonDict["horsepower"] as Double
license_plate = jsonDict["license_plate"] as String
}
}
struct Bicycle2 {
let vehicle: Vehicle2
let chainrings: Int
let sprockets: Int
init(jsonDict: JSONDict) {
vehicle = Vehicle2(jsonDict: jsonDict)
chainrings = jsonDict["chainrings"] as Int
sprockets = jsonDict["sprockets"] as Int
}
}
// MARK: - (3) struct, protocol + composition for parsing
// Solution 3:
// - keep value types, use a protocol
// - use intermediate struct only for parsing to keep encapsulation
// Issue: None… except code verbosity
protocol Vehicle3 {
var model: String { get }
var color: String { get }
}
private struct VehicleFields3 : Vehicle3 {
let model: String
let color: String
init(jsonDict: JSONDict) {
model = jsonDict["model"] as String
color = jsonDict["color"] as String
}
}
struct Car3 : Vehicle3 {
let model: String
let color: String
let horsepower: Double
let license_plate: String
init(jsonDict: JSONDict) {
let vehicle = VehicleFields3(jsonDict: jsonDict)
model = vehicle.model
color = vehicle.color
horsepower = jsonDict["horsepower"] as Double
license_plate = jsonDict["license_plate"] as String
}
}
struct Bicycle3 : Vehicle3 {
let model: String
let color: String
let chainrings: Int
let sprockets: Int
init(jsonDict: JSONDict) {
let vehicle = VehicleFields3(jsonDict: jsonDict)
model = vehicle.model
color = vehicle.color
chainrings = jsonDict["chainrings"] as Int
sprockets = jsonDict["sprockets"] as Int
}
}
// MARK: - (4) struct, protocols + global function for parsing
// Solution 4: [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 Vehicle4 {
var model: String { get set }
var color: String { get set }
}
private func parseVehicle4Fields(inout obj: Vehicle4, jsonDict: JSONDict) {
obj.model = jsonDict["model"] as String
obj.color = jsonDict["color"] as String
}
struct Car4 : Vehicle4 {
var model: String
var color: String
let horsepower: Double
let license_plate: String
init(jsonDict: JSONDict) {
parseVehicle4Fields(&self, jsonDict) // Error: Car4 is not identical to Vehicle4
horsepower = jsonDict["horsepower"] as Double
license_plate = jsonDict["license_plate"] as String
}
}
struct Bicycle4 : Vehicle4 {
var model: String
var color: String
let chainrings: Int
let sprockets: Int
init(jsonDict: JSONDict) {
parseVehicle4Fields(&self, jsonDict) // Error: Bicycle4 is not identical to Vehicle4
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