Protocol Oriented Programming boilerplate code

I am currently trying to implement some of the principles of protocol oriented programming to my data models. The problem is that I have quite a substantial amount of structs that conform to the protocol and I am finding that I have to write a lot of boilerplate code before my models can work with the protocols.


In the code below you can see that I have to provide an implementation for the "name" and "type" property everywhere. I am wondering if there is a way for me to declare these properties once and have it implemented for all the structs conforming to ColumnProtocol. I am aware that I can use extensions but these only provided computed properties (i.e. a get and set method) and I cannot use this.


protocol ColumnProtocol {
     var name: String {get}
     var type: ColumnType {get}
     var valueRange: [Any]? {get}
}

extension ColumnProtocol {
    //By default valueRange is nil
    var valueRange: [Any]? {
        get {
            return nil
        }
    }

}

struct BlueprintColumnDouble: BlueprintColumnProtocol{
    let type = ColumnType.double
    let name: String
}
struct BlueprintColumnInt: BlueprintColumnProtocol{
    let type = ColumnType.int
    let name: String
}
struct BlueprintColumnBoolean: BlueprintColumnProtocol{
    let type = ColumnType.boolean
    let name: String
}
struct BlueprintColumnDate: BlueprintColumnProtocol{
    let type = ColumnType.date
    let name: String
    let valueRange: [Any]?
   
    init(name: String, valueRange: [Any]?){
        if let _ = valueRange {
            let check = type.checkTypeOfArray(valueRange!)
            assert(check, "The value type for the range is not correct")
        }
        self.valueRange = valueRange
        self.name = name
    }
}


Thanks in advance.

Not that I'm aware of. And yes, I find it frustrating as well. Having a notation like "@autosynthesize <protocol_name> {get|set}" would be great ("get" would make get-only variables "let", and "set" would make them "var").

I think there might be a hacky, kinda sketchy workaround, though... If you can add a hashable ID variable, you could use computed variables declared in a protocol extension to access a private file-level dictionary using "self.ID" as the key and a tuple of the variables as the value. I think. I'll try it in a playground as soon as the latest Xcode beta is done installing.

Actually, it's very sketchy... Since structs don't have deinit functions, there isn't an automatic way of removing the relevant entry from the dictionary. It should work with classes, though.

This isn't an unreasonable feature request. Please file a bug report!

I think there's more going on here than you think.


What you're really asking for is inheritance, which currently does not exist for value types. Protocol extensions are vaguely similar to inheritance in some ways, but not currently so far as to allow you to have default stored properties.


You could use inheritance if your columns were classes instead of structs. Indeed, in this case, I think it's clear that your columns should be classes instead of structs. Generally, structs are inappropriate when their value represents the state of some thing, whether it's a real world object or a specific entity like a column (presumable of some table or list). In this case, a particular column has one true name, presumably along with other "one true" properties that you haven't shown us. If the column's one true state is immutable, it doesn't really matter whether it's a value type or a reference type, but if it's mutable as yours seems likely to be, then it's almost certainly better to use a reference type.


Incidentally, if your columns are immutable, then you'd still likely want to make them reference types (i.e. classes) because you have a valid need for inheritance in your design.


Unfortunately, POP has sent a lot of people (including me) scurrying in the direction of value types, but it's actually necessary to stop and think whether reference types might be a better solution.

Protocol Oriented Programming boilerplate code
 
 
Q