Swift,使用具有不同特定类型的通用属性 - 参考通用类型需要参数

发布于 2025-01-21 14:09:25 字数 1368 浏览 1 评论 0原文

一个人如何分配可以具有通用类型的类的实例,但是您不知道在运行时间之前是什么类型?

例如。

我们有一个协议和枚举,可以这样符合它:

protocol Stage: CaseIterable, Hashable {
    var fooBarLength: Int { get }
}

enum FirstStage: String, Stage {
    var fooBarLength: Int { 10 }
    case section1
    case section2
}

enum SecondStage: String, Stage {
    var fooBarLength: Int { 10 }
    case section1
    case section2
    case section3
}

接下来,我们将使用某种控制器,将协议用作通用类型...commeça...

class FooBarController<StageType: Stage>: UIViewController {
    private var stages: [StageType: Float] = [:]
}

然后是这样的:

func fooBarScreen(boop: SomethingThatKnowsAboutTheStages) {
    var fooBarController: FooBarController // <---- how do I define this????

    if boop.someCondition() {
        fooBarController = FooBarController<FirstStage>()
    } else {
        fooBarController = FooBarController<SecondStage>()
    }
}

在java / kotlin中,我可以做到这一点如上所述,我如何在Swift中实现同样的事情?

目前,我会得到

"Reference to generic type 'FooBarController' requires arguments in <...>"

次要问题

是否有比在这里使用它更通用的方法?理想情况下,我希望foobarscreen方法不关心通用类型,并且只有showerthatknatknowsaboutthestages为我提供类型。

How would one go about assigning an instance of a class which can have a generic type, but you don't know what type that is until run time?

For example.

We have a protocol and enums that conform to it like this:

protocol Stage: CaseIterable, Hashable {
    var fooBarLength: Int { get }
}

enum FirstStage: String, Stage {
    var fooBarLength: Int { 10 }
    case section1
    case section2
}

enum SecondStage: String, Stage {
    var fooBarLength: Int { 10 }
    case section1
    case section2
    case section3
}

Next we have some kind of controller that uses the protocol as a generic type... comme ça...

class FooBarController<StageType: Stage>: UIViewController {
    private var stages: [StageType: Float] = [:]
}

Then used like this:

func fooBarScreen(boop: SomethingThatKnowsAboutTheStages) {
    var fooBarController: FooBarController // <---- how do I define this????

    if boop.someCondition() {
        fooBarController = FooBarController<FirstStage>()
    } else {
        fooBarController = FooBarController<SecondStage>()
    }
}

In Java / Kotlin I could just do this as it is above, how do I achieve the same thing in Swift?

Currently I get

"Reference to generic type 'FooBarController' requires arguments in <...>"

Secondary Question

Is there a more generic way than having to use that if-statement here? Ideally I would like the fooBarScreen method to not care about the generic type and just have SomethingThatKnowsAboutTheStages provide the type for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怪我鬧 2025-01-28 14:09:25

您可以指定提供stage类型的协议,例如:

protocol StageProvider {
    
    associatedtype T: Stage
    
    func getType() -> T.Type
    
}

然后进行showerthatknatkaboutThestages或任何其他协议都符合此协议:

class SomethingThatKnowsAboutTheStages: StageProvider {
    
    typealias T = SecondStage
    
    func getType() -> T.Type {
        SecondStage.self
    }
    
}

为您的foobarcontroller :

class FooBarController<StageType: Stage>: UIViewController {
    
    convenience init(stage: StageType.Type) {
        self.init()
    }
    
}

最后使用所有这些:

func fooBarScreen<T: StageProvider>(boop: T) {
    let controller = FooBarController(stage: boop.getType())
}

You can specify a protocol for providing Stage types like so:

protocol StageProvider {
    
    associatedtype T: Stage
    
    func getType() -> T.Type
    
}

Then make your SomethingThatKnowsAboutTheStages or any other one conform this protocol:

class SomethingThatKnowsAboutTheStages: StageProvider {
    
    typealias T = SecondStage
    
    func getType() -> T.Type {
        SecondStage.self
    }
    
}

Add an initializer for your FooBarController:

class FooBarController<StageType: Stage>: UIViewController {
    
    convenience init(stage: StageType.Type) {
        self.init()
    }
    
}

And finally use all these:

func fooBarScreen<T: StageProvider>(boop: T) {
    let controller = FooBarController(stage: boop.getType())
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文