swift – 如何将类类型作为函数参数传递
我有一个通用的函数,调用一个Web服务,并将JSON响应序列化回一个对象。
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? }
你在错误的方式接近它:在Swift,不同于Objective-C,类有特定的类型,甚至有一个继承层次结构(也就是说,如果B类继承自A,那么B.Type也继承自A.Type):
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,您可以为编译器提供一种确定通用参数的方法。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |