3

I have a protocol called Parameter:

protocol Parameter {

    var name: String { get }
    var unit: Unit? { get }
    var value: Double { get }

    init(name: String, unit: Unit?, value: Double)

}

I also have 16 structs that conform to Parameter:

struct Calcium: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Calcium", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Alkalinity: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Alkalinity", unit: Unit? = Unit(symbol: "ppm CaCO3"), value: Double) {
        self.name = name
       self.unit = unit
        self.value = value
    }

} 

struct Salinity: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Salinity", unit: Unit? = Unit(symbol: "SG"), value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

} 

struct Temperature: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Temperature", unit: Unit? = UnitTemperature.fahrenheit, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct PH: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "pH", unit: Unit? = nil, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Magnesium: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Magnesium", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Phosphate: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Phosphate", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Ammonia: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Ammonia", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Silica: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Silica", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Iodine: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Iodine", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Nitrate: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Nitrate", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Nitrite: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Nitrite", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Strontium: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Strontium", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct ORP: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "ORP", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

struct Boron: Parameter {

    var name: String
    var unit: Unit?
    var value: Double

    init(name: String = "Boron", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

    struct Iron: Parameter {

        var name: String
        var unit: Unit?
        var value: Double

        init(name: String = "Iron", unit: Unit? = UnitDispersion.partsPerMillion, value: Double) {
            self.name = name
            self.unit = unit
            self.value = value
        }

    }

As you can see, all of the structs implement the same initializer. In the initializer, I provide default values for two of the three parameters required by the Parameter protocol, which gives me the following initializer:

let calcium = Calcium(value: Double)

I also get the default initializer created by the structs:

let calcium = Calcium(name: String, unit: Unit?, value: Double)

When I am creating instances of the structs, both initializers appear in Xcode's code completion popover. However, I don't want the name and unit parameters to be able to be anything different than the default values provided in the initializer. I have also tried assigning default values for the name and unit properties where the they are declared inside of the struct but outside of the initializer required by the Parameter protocol.

Is there a way to initialize the structs by providing default values for the name and unit parameters, requiring only the value parameter to be provided, while not having the default initializer show in Xcode's code completion popup?

The only concern that I have with having both initializers appear in Xcode's code completion popup is that I don't want someone else creating structs and providing values other than the ones that I have provided in the initializer required by the Parameter protocol.

I realize that I could do so with a class, but I am trying to get my mind right with protocol-oriented programming and using structs.

Nick Kohrn
  • 5,779
  • 3
  • 29
  • 49

1 Answers1

1

One way to do it:

We changed all variables to optionals, and removed initializer with default parameters from protocol. If unit and value are going to have default values always, there is no need for client to see this initializer.

protocol Parameter {
    var name: String? { get }
    var unit: Unit? { get }
    var value: Double? { get }
    //init(name: String, unit: Unit?, value: Double)
    init(value: Double)
}

And change structure to look like this:

struct Calcium: Parameter {

    var name: String? = nil
    var unit: Unit? = nil
    var value: Double? = nil

    init(value: Double) {
        self.init(name: "Calcium", unit: UnitDispersion.partsPerMillion, value: value)
    }

    private init(name: String, unit: Unit, value: Double) {
        self.name = name
        self.unit = unit
        self.value = value
    }

}

In structure itself, we have added private initializer, which is called from custom initializer requiring only one parameter.

And you will have only one initializer in Xcode completion popup. image

Martin Berger
  • 1,639
  • 3
  • 18
  • 39