class func invokeService<T>(service: String,withParams params: Dictionary<String,String>,returningClass: AnyClass,completionHandler handler: ((T) -> ())) { /* Construct the URL,call the service and parse the response */ }
我想要完成的是相当于这个Java代码
public <T> T invokeService(final String serviceURLSuffix,final Map<String,String> params,final Class<T> classTypeToReturn) { }
首先,我的方法签名我想要完成什么?更具体地说,是指定AnyClass作为参数类型正确的事情吗?
此外,当调用方法时,我传递MyObject.self作为returningClass值,但我得到一个编译错误“无法转换表达式的类型'()’类型’字符串’
CastDAO.invokeService("test",withParams: ["test" : "test"],returningClass: CityInfo.self) { cityInfo in /*...*/ }
任何帮助将不胜感激。
谢谢
编辑:我尝试使用object_getClass,由holex提及,现在我得到这个错误:“类型’CityInfo.Type’不符合协议’AnyObject’”。需要做什么以符合协议?
class CityInfo : NSObject { var cityName: String? var regionCode: String? var regionName: String? }
class A {} class B: A {} class C {} // B inherits from A let object: A = B() // B.Type also inherits from A.Type let type: A.Type = B.self // Error: 'C' is not a subtype of 'A' let type2: A.Type = C.self
这就是为什么你不应该使用AnyClass,除非你真的想允许任何类。在这种情况下,正确的类型将是T.Type,因为它表达了returningClass参数和闭包的参数之间的链接。
事实上,使用它而不是AnyClass允许编译器正确地推断方法调用中的类型:
class func invokeService<T>(service: String,returningClass: T.Type,completionHandler handler: ((T) -> ())) { // The compiler correctly infers that T is the class of the instances of returningClass handler(returningClass()) }
现在有一个问题,构造一个T的实例传递给处理程序:如果你现在尝试并运行代码,编译器会抱怨T不是可构造的()。正确的是:T必须明确地限制要求它实现一个特定的初始化器。
这可以通过像下面这样的协议来完成:
protocol Initable { init() } class CityInfo : NSObject,Initable { var cityName: String? var regionCode: String? var regionName: String? // Nothing to change here,CityInfo already implements init() }
然后你只需要改变invokeService的泛型约束,从< T>到< T:Initable> ;. 小费 如果你得到奇怪的错误,如“无法将表达式的类型()’转换为类型”字符串“,通常有用的是将方法调用的每个参数移动到自己的变量。它有助于缩小导致错误的代码并揭示类型推断问题:
let service = "test" let params = ["test" : "test"] let returningClass = CityInfo.self CastDAO.invokeService(service,withParams: params,returningClass: returningClass) { cityInfo in /*...*/ }
现在有两种可能性:错误移动到其中一个变量(这意味着错误的部分存在)或者你得到一个隐藏的消息,如“无法将表达式的type()转换为类型($ T6) – >($ T6)→> $ T5“。
后一个错误的原因是编译器不能推断你写的类型。在这种情况下,问题是T只用在闭包的参数中,而你传递的闭包不指示任何特定类型,所以编译器不知道要推断什么类型。通过更改returningClass的类型以包括T,您可以为编译器提供一种确定通用参数的方法。