Есть ли способ скрыть инициализатор по умолчанию для Swift Struct?

У меня есть протокол под названием Parameter:

protocol Parameter {

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

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

}

У меня также есть 16 структур, соответствующих 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
        }

    }

Как видите, все структуры реализуют один и тот же инициализатор. В инициализаторе я задаю значения по умолчанию для двух из трех параметров, требуемых протоколом Parameter, что дает мне следующий инициализатор:

let calcium = Calcium(value: Double)

Я также получаю инициализатор по умолчанию, созданный структурами:

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

Когда я создаю экземпляры структур, оба инициализатора появляются во всплывающем окне завершения кода Xcode. Однако я не хочу, чтобы параметры name и unit могли отличаться от значений по умолчанию, предоставленных в инициализаторе. Я также попытался назначить значения по умолчанию для свойств name и unit, где они объявлены внутри структуры, но вне инициализатора, требуемого протоколом Parameter.

Есть ли способ инициализировать структуры, указав значения по умолчанию для параметров name и unit, требуя предоставления только параметра value, при этом инициализатор по умолчанию не отображается во всплывающем окне завершения кода Xcode?

Единственное беспокойство, которое у меня вызывает появление обоих инициализаторов во всплывающем окне завершения кода Xcode, заключается в том, что я не хочу, чтобы кто-то еще создавал структуры и предоставлял значения, отличные от тех, которые я предоставил в инициализаторе, требуемом протоколом Parameter.

Я понимаю, что мог бы сделать это с помощью класса, но я пытаюсь разобраться в протокольно-ориентированном программировании и использовании структур.


person Nick Kohrn    schedule 25.08.2016    source источник


Ответы (1)


Один из способов сделать это:

Мы изменили все переменные на необязательные и удалили инициализатор с параметрами по умолчанию из протокола. Если unit и value будут иметь значения по умолчанию всегда, клиенту не нужно видеть этот инициализатор.

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

И измените структуру, чтобы она выглядела так:

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
    }

}

В самой структуре мы добавили частный инициализатор, который вызывается из пользовательского инициализатора, требующего только один параметр.

И у вас будет только один инициализатор во всплывающем окне завершения Xcode. изображение

person Martin Berger    schedule 12.10.2016