我可以在Swift中为泛型类型T指定默认类型吗?

ter*_*dyl 24 generics swift

我有一个泛型类,我希望能够使用默认类型.现在我可以用任何类型初始化它,但我必须明确.

//Initialize with a type
MyManager<MyCustomerObject>()

// Initialize with NSObject (what I want to be my default type)
MyManager<NSObject>()

// This doesn't work, but I want this kind of functionality
class MyManager<T = NSObject> {}

// So I can create my manager like so and it inserts the default type as NSObject
MyManager() //Or MyManager<>()
Run Code Online (Sandbox Code Playgroud)

这在Swift中可能吗?

mar*_*rux 31

不支持默认泛型参数,但您可以通过init()在类型受限扩展上定义默认值来伪造它,在这种情况下,编译器将足够智能以使用该类型。例如:

class MyManager<T> {
    let instance: T

    init(instance: T) {
        self.instance = instance
    }
}

extension MyManager where T == NSObject {
    convenience init() {
        self.init(instance: NSObject())
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以不带参数初始化类型,它会默认为MyManager<NSObject>

let mm1 = MyManager(instance: "Foo") // MyManager<String>
let mm2 = MyManager(instance: 1) // MyManager<Int>
let mm3 = MyManager() // MyManager<NSObject>
Run Code Online (Sandbox Code Playgroud)

SwiftUI 大量使用这种技术。

  • 我一直在绞尽脑汁试图弄清楚 SwiftUI 是如何做到这一点的,非常感谢。我真的希望将来 Swift 能够实现某种 `init() where T==NSObject` 语法。 (2认同)

Ham*_*ish 28

不,这目前是不可能的 - 尽管它是Generics Manifesto一部分,因此Swift团队可能会考虑使用该语言的未来版本.

默认通用参数

通用参数可以被赋予提供默认参数的能力,这些参数将在未指定type参数且类型推断无法确定类型参数的情况下使用.例如:

public final class Promise<Value, Reason=Error> { ... }

func getRandomPromise() -> Promise<Int, Error> { ... }

var p1: Promise<Int> = ... 
var p2: Promise<Int, Error> = p1     // okay: p1 and p2 have the same type Promise<Int, Error>
var p3: Promise = getRandomPromise() // p3 has type Promise<Int, Error> due to type inference
Run Code Online (Sandbox Code Playgroud)

然而,与此同时,一个令人不满意的折衷方案是使用typealias:

class MyManager<T> {}

typealias MyManagerDefault = MyManager<NSObject>

let defaultManager = MyManagerDefault()
Run Code Online (Sandbox Code Playgroud)

不像刚才能说的那么光滑MyManager(),但它确实出现MyManager在自动完成旁边,这非常方便.