2014-10-20 157 views
0

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

在C++中,我能做到这一点:

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

,我可以做到这一点,从获取特定ComponentEntity

Entity().getComponent<LifeComponent>(); 

我想重现此斯威夫特,但我无法弄清楚如何实现它。

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

在斯威夫特:

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

我希望能够做到:

Entity().get<LifeComponent>() 

你能帮助我吗?

+3

[谷歌,先打:官方文档(https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26 -XID_278)。 [谷歌,第三击:教程](http://www.codingexplorer.com/generic-functions-in-swift/)。您不必“弄清楚”这一点:使用Google并阅读文档就足够了。 – 2014-10-20 13:11:53

+0

我知道如何创建泛型函数,以及如何使用它。我只想知道是否有一种方法可以像C++中那样在Swift中传入一个类型。 – cappie013 2014-10-20 13:21:32

回答

0

这是尽可能接近你想要做的事情的精神。

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

// 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)") 
0

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

Swift必须知道,在编译时什么你会传递到get()函数。它不会盲目地接受你提供的任何内存。编译器必须被告知内存中会有什么。

下面是描述如何使用泛型的斯威夫特,这应该回答你所有的问题的文档: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++编写的代码集成。

+0

“Swift在编译时必须知道你要传入get()函数的内容。” 'get()'函数不带任何参数;没有什么是“传入”的。 – newacct 2014-10-22 07:31:20

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") 
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。在此之前从未测试过版本。