简体   繁体   English

如何使用通用默认参数

[英]How to use generic default parameters

This is my code: 这是我的代码:

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

enum Child: String {
    case johnDoe
}

It doesn't compile. 它不会编译。 The error is: 错误是:

Default argument value of type 'Child' cannot be converted to type 'T' 类型'Child'的默认参数值不能转换为类型'T'

Why can't it be converted? 为什么不能转换? According to the docs , Child.someEnum is RawRepresentable : 根据文档Child.someEnumRawRepresentable

Enumerations with Raw Values For any enumeration with a string, integer, or floating-point raw type, the Swift compiler automatically adds RawRepresentable conformance. 具有原始值的枚举对于任何具有字符串,整数或浮点原始类型的枚举,Swift编译器都会自动添加RawRepresentable一致性。 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. 定义自己的自定义枚举时,可以通过将原始类型指定为枚举的类型继承列表中的第一项来为其提供原始类型。

This also compiles: 这也可以编译:

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

enum Child: String {
    case johnDoe
}

Person.accept(raw: Child.johnDoe)

Why doesn't it work as a default parameter? 为什么它不能用作默认参数?

Use case: I want to accept any RawPresentable value, so I can extract the rawValue from it. 用例:我想接受任何RawPresentable值,因此我可以从中提取rawValue I want to provide a default value (always "") (I just create a struct with rawValue = "" ). 我想提供一个默认值(总是“”)(我只是用rawValue = ""创建一个结构)。 I do not want to create multiple initializers, since I got some subclasses and that would get a mess. 我不想创建多个初始化器,因为我得到了一些子类,那样一团糟。 The best for me is just to provide a default RawRepresentable object. 对我而言,最好的办法就是提供一个默认的RawRepresentable对象。

When I add a cast: init(ty: T = (Child.johnDoe as! T)) where T.RawValue == String { 当我添加演员表时:init(ty:T =(Child.johnDoe as!T)),其中T.RawValue ==字符串{

}

Or make it nillable: 或将其设为nillable:

(ty: T? = nil)

It compiles. 它编译。 But now I can not call: 但是现在我不能打电话:

let x = Person()

It gives the error: 它给出了错误:

Generic parameter 'T' could not be inferred 无法推断通用参数“ T”

This is certainly possible. 这当然是可能的。 However, you have to use your own protocol and add the default value to that protocol: 但是,您必须使用自己的协议并将默认值添加到该协议:

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
}

There is another issue though. 但是还有另一个问题。 How will you specify the generic type if you use the default parameter value and all you will have will be just Person.init() ? 如果使用默认参数值,那么将如何指定泛型类型,而只剩下Person.init()呢?

The only solution I see is to also specify a default generic type which means you actually want: 我看到的唯一解决方案是还指定默认的泛型类型,这意味着您实际需要:

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

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

Unless you actually want to make Person itself a generic class because then you could just use 除非您实际上想使Person本身成为泛型类,否则您可以使用

Person<Child>.init()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM