swift Swift,Struct和Inheritance:如何平衡使用Struct和Value Types的意愿以及继承的需要?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift Swift,Struct和Inheritance:如何平衡使用Struct和Value Types的意愿以及继承的需要?相关的知识,希望对你有一定的参考价值。

// #!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
    }
}

以上是关于swift Swift,Struct和Inheritance:如何平衡使用Struct和Value Types的意愿以及继承的需要?的主要内容,如果未能解决你的问题,请参考以下文章

swift Class和struct的区别

swift Swift - 使用Struct进行Segue

swift 在swift中收集单词的struct

Swift class和struct异同点

Swift之struct二进制大小分析

Swift之struct二进制大小分析