Swift中的通用函数

时间:2014-10-20 13:00:18

标签: generics swift

我来自C ++,我对Swift中的泛型函数有点困惑。

在C ++中,我可以这样做:

class Entity
{
    template    <typename T>
    T *getComponent()
    {
        return (T *)(listComponent_[typeid(T).name()]);
    }
};

我可以执行此操作以从我的Component

中获取特定的Entity
Entity().getComponent<LifeComponent>();

我想在Swift中重现这一点,但我无法弄清楚如何实现它。

在Swift中,我必须为我的函数定义一个参数来确定我的类型。

在斯威夫特:

class Entity
{
    func get<T>() -> T
    {
         return ??
    }
}

我希望能够做到:

Entity().get<LifeComponent>()

你能帮助我吗?

4 个答案:

答案 0 :(得分:1)

我不了解C ++语法,但也许你想要的是这样的?

class Entity {
    var list:[Any] = []

    func register(obj:Any) {
        list.append(obj)
    }
    func getComponent<T>(type:T.Type) -> T? {
        for obj in list {
            if let instance = obj as? T {
                return instance
            }
        }
        return nil
    }
}

let cls = Entity()
cls.register(1)
cls.register("This is a String")
cls.register(UIView())
cls.register(1.01)

cls.getComponent(String) // -> Optional("This is a String")

答案 1 :(得分:0)

你需要告诉编译器它可以用T做什么,否则它几乎没用。

Swift必须知道,在编译时你将传递给get()函数。它不会盲目接受你提供的任何内存。必须告诉编译器该内存中的内容。

以下是描述如何在Swift中使用泛型的文档,它应该回答您的所有问题:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html

另一个选择是你可以使用Objective-C甚至是C ++。

iOS和OS X的大多数软件都是用Objective-C或C / C ++编写的。目前几乎没有任何东西是用Swift编写的,而且语言是完全可行语言的年限。主要用Swift编写的项目可以很好地与用Objective-C或C / C ++编写的代码集成。

答案 2 :(得分:0)

这就像我能够达到你想要做的精神一样接近。

在这种情况下,我们正在定义一个协议,告诉Entity如何获取组件的名称。使其明确将使其比获取变量的类型名称或类的名称的任何黑客更加可靠和易读,所有这些都有多个限制。请注意,如果组件都具有公共超类,或者即使它们都是NSObject的所有子类,也可以大大简化这一点。无论如何,使用协议方法可能是最好的,因为您的实体中的内容,无论它们是什么是的,应该都有一些共同的共享界面,否则你不知道你能用它做什么。

// Mostly the Component protocol is needed so that we can create an
//  item with no arguments.
protocol NamedComponent {
    class var ComponentName : String { get }
}

// Make Int an allowable component
extension Int : NamedComponent {
    static let ComponentName = "Int"
}

extension String : NamedComponent {
    static let ComponentName = "String"
}

// make a class a NamedComponent, note the different syntax between
// adding a class constant to a class here and to a struct or base type
// above
class SomeComponent : NamedComponent {
    class var ComponentName : String { get { return "SomeComponent" } }
}

class Entity {
    // The component library
    var components = [String:NamedComponent]()

    // add a component to the library by class name
    func register<T:NamedComponent>(value:T) {
        components[T.ComponentName] = value
    }

    // Reference a component by class name
    func get<T:NamedComponent>() -> T? {
        return components[T.ComponentName] as? T
    }
}

// Create the entity
let entity = Entity()

// Add a dummy component
entity.register(45)
entity.register("string")
entity.register(SomeComponent())

// Fetch a dummy component
let int : Int? = entity.get()
println("\(int)")

let str : String? = entity.get()
println("\(str)")

let comp : SomeComponent? = entity.get()
println("\(comp)")

答案 3 :(得分:0)

偶然发现了同样的问题。如何调用泛型函数?

为我找到了解决方案,也许它也适合你。我有一些结构,我想从字典初始化。我的所有结构都实现了协议DictionaryInitializable

struct MyStruct: DictionaryInitializable {
    ...
    init?(dictionary: [String: AnyObject]) {
        ...
    }
}

我还有一个使用以下方法的解析器:

func parse<T: DictionaryInitializable>(dict: [String: AnyObject]) -> T? {
    return T(dictionary: dict)
}

要使用该功能,您可以使用以下代码:

let parsedStruct: MyStruct = parser.parse(dictionary)

这适用于Xcode 7.3和Swift 2.2。从未在此之前的版本中进行测试。