如何使用通用默认参数
How to use generic default parameters
这是我的代码:
class Person {
init<T: RawRepresentable>(raw: T = Child.johnDoe) {}
}
enum Child: String {
case johnDoe
}
它不编译。错误是:
Default argument value of type 'Child' cannot be converted to type 'T'
为什么不能转换?根据docs,Child.someEnum
是RawRepresentable
:
Enumerations with Raw Values For any enumeration with a string,
integer, or floating-point raw type, the Swift compiler automatically
adds RawRepresentable conformance. When defining your own custom
enumeration, you give it a raw type by specifying the raw type as the
first item in the enumeration’s type inheritance list.
这也编译:
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 as!T)) 其中 T.RawValue == String {
}
或者让它可以为空:
(ty: T? = nil)
编译通过。但是现在我不能打电话了:
let x = Person()
它给出了错误:
Generic parameter 'T' could not be inferred
这当然是可能的。但是,您必须使用自己的协议并将默认值添加到该协议:
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
本身成为通用的 class 因为那样你就可以使用
Person<Child>.init()
这是我的代码:
class Person {
init<T: RawRepresentable>(raw: T = Child.johnDoe) {}
}
enum Child: String {
case johnDoe
}
它不编译。错误是:
Default argument value of type 'Child' cannot be converted to type 'T'
为什么不能转换?根据docs,Child.someEnum
是RawRepresentable
:
Enumerations with Raw Values For any enumeration with a string, integer, or floating-point raw type, the Swift compiler automatically adds RawRepresentable conformance. When defining your own custom enumeration, you give it a raw type by specifying the raw type as the first item in the enumeration’s type inheritance list.
这也编译:
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 as!T)) 其中 T.RawValue == String {
}
或者让它可以为空:
(ty: T? = nil)
编译通过。但是现在我不能打电话了:
let x = Person()
它给出了错误:
Generic parameter 'T' could not be inferred
这当然是可能的。但是,您必须使用自己的协议并将默认值添加到该协议:
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
本身成为通用的 class 因为那样你就可以使用
Person<Child>.init()