如何将类类型作为函数参数传递
我有一个通用函数,该函数调用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, withParams params: Dictionary<String, String>, returningClass: T.Type, completionHandler handler: ((T) -> ())) { // The compiler correctly infers that T is the class of the instances of returningClass
handler(returningClass())
}
现在存在构造T
要传递给的实例的问题handler
:如果您现在尝试运行代码,则编译器将抱怨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>
。
回答:
如果遇到诸如“无法将表达式的类型’()’转换为’String’类型”之类的奇怪错误,将方法调用的每个参数移至其自己的变量通常很有用。它有助于缩小导致错误的代码范围,并揭示类型推断问题:
let service = "test"let params = ["test" : "test"]
let returningClass = CityInfo.self
CastDAO.invokeService(service, withParams: params, returningClass: returningClass) { cityInfo in /*...*/
}
现在有两种可能性:错误移至变量之一(这意味着存在错误的部分),或者您收到诸如“无法将表达式的类型转换()
为类型($T6) -> ($T6) ->
$T5” 之类的神秘信息。
后一个错误的原因是编译器无法推断您编写的内容的类型。在这种情况下,问题在于T
仅在闭包的参数中使用,并且您传递的闭包没有指示任何特定类型,因此编译器不知道要推断的类型。通过更改包含的类型,returningClass
可以T
为编译器提供一种确定通用参数的方法。
以上是 如何将类类型作为函数参数传递 的全部内容, 来源链接: utcz.com/qa/408779.html