Есть ли способ скрыть инициализатор по умолчанию для 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 протокол.

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

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. образ

Другие вопросы по тегам