【问题标题】:Create instance of class based on function argument [duplicate]基于函数参数创建类的实例[重复]
【发布时间】:2018-01-03 11:12:07
【问题描述】:

假设我有三个类:

import Foundation

class A {

    init() {
      print("A")
    }

}

class B {

    init() {
        print("B")
    }

}

class C {

    init() {
       print("C")
    }
}

我想动态地传递一个字符串(“A”、“B”或“C”)作为函数参数,然后在这个函数的主体内,创建一个我传递的类的实例。这可能吗?怎么样?

我试过这个(和其他变种)但没有运气:

func test(c:AnyObject){
    let _class = c()
    //...
}

test(c:A)

[更新] 也许这个问题与@Code Different 建议的问题没有什么不同,但这个问题很老,而且语言发生了很多变化,人们应该先尝试任何建议的解决方案,然后才能找到今天有效的解决方案

【问题讨论】:

    标签: swift function class instantiation


    【解决方案1】:

    可以有一个基类,我们称之为BaseClass。需要使用的类将继承自BaseClass

    然后,在您的函数中,您可以将所需的类型传递给它。

    下面是演示此技术的代码 sn-p:

    class BaseClass { }
    
    class A: BaseClass { ... }
    class B: BaseClass { ... }
    class C: BaseClass { ... }
    
    func test(type: BaseClass.Type) {
        let someObject = type.init()
        // You can cast the object if required
    }
    
    test(type: A.self) // creates an object of class A
    test(type: B.self) // creates an object of class B
    

    编辑: 如果你真的需要一个字符串来转换你的类型,你可以考虑在调用test之前做一些工作。在 switch case 中获取类型,然后将其传递给 test 应该可以。

    编辑:它也适用于协议,只要它定义了您需要的初始化程序,以及必须公开的每个函数:

    protocol SomeProtocol: class {
        init()
        func someFunction()
    }
    
    class A {
        required init() {
            print("A")
        }
    }
    
    extension A: SomeProtocol {
        func someFunction() {
            print("Some function of A")
        }
    }
    
    class B {
        required init() {
            print("B")
        }
    }
    
    extension B: SomeProtocol {
        func someFunction() {
            print("Some function of B")
        }
    }
    
    class C {
        required init() {
            print("C")
        }
    }
    
    extension C: SomeProtocol {
        func someFunction() {
            print("Some function of C")
        }
    }
    
    func test(someType: SomeProtocol.Type) {
        let someObject: SomeProtocol = someType.init()
        someObject.someFunction()
    }
    
    test(someType: A.self) // creates an object of class A
    test(someType: B.self) // creates an object of class B
    

    【讨论】:

    • 协议不起作用,而 BaseClass 只要您添加所需的 init 就可以工作。我无法编辑您的代码,但我想这 let someObject type.init() 应该是 let someObject = type.init()
    • @3000 添加了一个与协议一起工作的版本,在 Playground 中进行了测试。协议需要定义类使用的初始化器。
    • 它工作正常,但我发现,如果你为每个类添加一个方法,你也必须将它添加到协议中
    • @3000 是的,最好通过添加外部所需的每个 API 来定义您的协议。否则,您必须强制转换对象以了解他具有的特定功能(那些不在协议中的功能)。我添加了一些更改,显示了一种方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 2017-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    相关资源
    最近更新 更多