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

时间:2017-02-03 01:01:31

标签: swift generics

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

//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<>()

这可以在Swift中使用吗?

3 个答案:

答案 0 :(得分:23)

不,这当前是不可能的 - 尽管它是part of the Generics Manifesto,因此Swift团队可能会考虑使用该语言的未来版本。

  

默认通用参数

     

通用参数可以提供默认的能力   参数,将在类型参数不是的情况下使用   指定和类型推断无法确定类型参数。   例如:

if (hero.health > 0)

与此同时,一个令人不满意的折衷方案是使用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

typealias

不像只能说class MyManager<T> {} typealias MyManagerDefault = MyManager<NSObject> let defaultManager = MyManagerDefault() 那么光滑,但它确实显示在自动完成的MyManager()旁边,这非常方便。

答案 1 :(得分:1)

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

class MyManager<T> {
    let instance: T

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

extension MyManager where T == NSObject {
    convenience init() {
        self.init(instance: NSObject())
    }
}

现在您可以不使用参数来初始化类型,它将默认为MyManager<NSObject>

let mm1 = MyManager(instance: "Foo") // MyManager<String>
let mm2 = MyManager(instance: 1) // MyManager<Int>
let mm3 = MyManager() // MyManager<NSObject>

SwiftUI经常使用这种技术。

答案 2 :(得分:1)

如果 T 始终是 NSObject 子类,则可以在 Swift 5.3 中使用通用约束:

class MyManager<T: NSObject> {
    let t = T()
}

class MyCustomerObject: NSObject { }

let a = MyManager()
let b = MyManager<MyCustomerObject>()