Как использовать общие параметры по умолчанию - PullRequest
0 голосов
/ 12 февраля 2019

Это мой код:

class Person {
    init<T: RawRepresentable>(raw: T = Child.johnDoe) {}
}

enum Child: String {
    case johnDoe
}

Не компилируется.Ошибка:

Значение аргумента по умолчанию типа 'Child' не может быть преобразовано в тип 'T'

Почему его нельзя преобразовать?Согласно docs , Child.someEnum равно RawRepresentable:

Перечисления с необработанными значениями Для любого перечисления со строковым, целочисленным или необработанным типом с плавающей точкой SwiftКомпилятор автоматически добавляет соответствие RawRepresentable.При определении собственного настраиваемого перечисления вы задаете ему необработанный тип, указав необработанный тип в качестве первого элемента в списке наследования типов перечисления.

Также компилируется:

class Person {
    static func accept<T: RawRepresentable>(raw: T) where T.RawValue == String {}
}

enum Child: String {
    case johnDoe
}

Person.accept(raw: Child.johnDoe)

Почему он не работает как параметр по умолчанию?

Вариант использования: я хочу принять любое значение RawPresentable, чтобы извлечь из него rawValue.Я хочу предоставить значение по умолчанию (всегда "") (я просто создаю структуру с rawValue = "").Я не хочу создавать несколько инициализаторов, так как у меня есть несколько подклассов, и это может привести к путанице.Лучшее для меня - просто предоставить объект по умолчанию RawRepresentable.

Когда я добавлю приведение типа: init (ty: T = (Child.johnDoe! T)), где T.RawValue == String {

}

Или сделать это с гвоздем:

(ty: T? = nil)

Компилируется.Но теперь я не могу позвонить:

let x = Person()

Выдает ошибку:

Общий параметр 'T' не может быть выведен

1 Ответ

0 голосов
/ 12 февраля 2019

Это, конечно, возможно.Однако вы должны использовать свой собственный протокол и добавить значение по умолчанию к этому протоколу:

protocol MyRawRepresentable: RawRepresentable {
    static var defaultValue: Self { get }
}

class Person {
    init<T: MyRawRepresentable>(raw: T = T.defaultValue) {}
}

enum Child: String, MyRawRepresentable {
    case johnDoe

    static let defaultValue: Child = .johnDoe
}

Однако существует еще одна проблема.Как вы будете определять универсальный тип, если будете использовать значение параметра по умолчанию, и все, что у вас будет, будет просто Person.init()?

Единственное решение, которое я вижу, это также указать универсальный тип по умолчанию, что означает, что вы действительно хотите:

class Person {
   init<T: RawRepresentable>(raw: T) {
   }

   convenience init() {
       self.init(raw: Child.johnDoe)
   }
}

Если вы на самом деле не хотите сделать Person общим классом, потому что тогда вы можете просто использовать

Person<Child>.init()
...