如何使用通用默认参数

时间:2019-02-12 19:30:57

标签: swift parameters rawrepresentable

这是我的代码:

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

enum Child: String {
    case johnDoe
}

它不能编译。错误是:

  

类型'Child'的默认参数值不能转换为类型'T'

为什么不能转换?根据{{​​3}},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))其中T.RawValue ==字符串{

}

或者将其设置为可校正:

(ty: T? = nil)

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

let x = Person()

出现错误:

  

无法推断出通用参数'T'

1 个答案:

答案 0 :(得分: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
}

但是还有另一个问题。如果您使用默认参数值,那么将如何指定通用类型,而您所拥有的仅仅是Person.init()

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

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

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

除非您实际上想使Person本身成为泛型类,否则您就可以使用

Person<Child>.init()