Как использовать общие параметры по умолчанию
Это мой код:
class Person {
init<T: RawRepresentable>(raw: T = Child.johnDoe) {}
}
enum Child: String {
case johnDoe
}
Это не компилируется. Ошибка:
Значение аргумента по умолчанию типа 'Child' не может быть преобразовано в тип 'T'
Почему это не может быть преобразовано? Согласно документам, 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 ответ
Это конечно возможно. Однако вы должны использовать свой собственный протокол и добавить значение по умолчанию для этого протокола:
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()