3

这是我的代码:

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

enum Child: String {
    case johnDoe
}

它不编译。错误是:

“Child”类型的默认参数值无法转换为“T”类型

为什么不能转换?根据文档Child.someEnumRawRepresentable

带有原始值的枚举 对于任何带有字符串、整数或浮点原始类型的枚举,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 as!T)) where T.RawValue == String {

}

或使其可空:

(ty: T? = nil)

它编译。但现在我不能打电话:

let x = Person()

它给出了错误:

无法推断通用参数“T”

4

1 回答 1

3

这当然是可能的。但是,您必须使用自己的协议并将默认值添加到该协议:

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
}

不过还有另一个问题。如果您使用默认参数值,您将如何指定泛型类型,而您将拥有的只是 just Person.init()

我看到的唯一解决方案是还指定一个默认的泛型类型,这意味着您实际上想要:

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

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

除非你真的想让Person自己成为一个泛型类,因为那样你就可以使用

Person<Child>.init()
于 2019-02-12T19:53:59.967 回答