我创建了以下功能:
func getArray<T : ROJSONObject>(key:String) -> T[] { var elements = T[]() for jsonValue in getValue(key).array! { var element = T() element.jsonData = jsonValue elements.append(element) } return elements }
现在我想在调用该方法时传递类型,所以它知道应该在内部创建哪个类型.我认为在Java和C#中,你可以使用这样的方法:
object.getArray<Document>("key")
当我这样称呼,我总是得到错误:
Cannot explicitly specialize a generic function
所以我的修复是定义一个附加参数,包含一个类型T的实例,所以它会自动检测类型:
func getArray<T : ROJSONObject>(key:String,type:T) -> T[] { var elements = T[]() for jsonValue in getValue(key).array! { var element = T() element.jsonData = jsonValue elements.append(element) } return elements }
在没有传递未使用的实例的情况下,真的没有其他方法来获得这种行为吗?还是我误解的东西?
进一步测试
在jtbandes的答案之后,我做了一些更多的测试.我试图通过在呼叫中添加as来强制类型.
class Person { init() { } func getWorkingHours() -> Float { return 40.0 } } class Boss : Person { override func getWorkingHours() -> Float { println(100.0) return 100.0 } } class Worker : Person { override func getWorkingHours() -> Float { println(42.0) return 42.0 } } func getWorkingHours<T : Person>() -> T { var person = T() person.getWorkingHours() return person } var worker:Worker = getWorkingHours() as Worker var boss:Boss = getWorkingHours() as Boss worker.getWorkingHours() // prints out 40.0 instead of 42.0 boss.getWorkingHours() // prints out 40.0 instead of 100.0
所以不知何故,类型始终是基本类型,即使我已经指定了具有as关键字的类型.我知道这个例子没有什么意义,但它只是用于测试目的.
您可以通过将类作为NSObject的子类或使用@required标记基类的构造函数来解决此问题
import Cocoa class A : NSObject { init() { } } class B : A {} class C : A {} func Create<T:NSObject> () -> T { return T() } println(Create() as A) println(Create() as B) println(Create() as C) //<_TtC11lldb_expr_01A: 0x7f85ab717bc0> //<_TtC11lldb_expr_01B: 0x7f85ab451e00> //<_TtC11lldb_expr_01C: 0x7f85ab509160> class D { @required init() { } } class E : D { init() { } } class F : D { init() { } } func Create2<T:D> () -> T { return T() } println(Create2() as D) println(Create2() as E) println(Create2() as F) //C11lldb_expr_01D (has 0 children) //C11lldb_expr_01E (has 1 child) //C11lldb_expr_01F (has 1 child)
不知道为什么@required解决问题.但是this is the reference
Apply this attribute to a designated or convenience
initializer of a class to indicate that every subclass must implement
that initializer.required designated initializers must be implemented explicitly. required convenience initializers can be either implemented explicitly or inherited when the subclass directly implements all of the superclass’s designated initializers (or when the subclass overrides the designated initializers with convenience initializers).