在父类上创建一个所有子类都可以访问的函数 [英] Creating a function on a parent class that can be accessible to all it's child classes
问题描述
我正在尝试在其子类可以访问的父类中创建一个函数.我遇到的问题是该功能的一部分,它是指需要在子类中发生的init.我收到一个错误:
I'm trying to create a function in a parent class that can be accessible to it's child classes. The issue I'm having is part of the function is referring to an init that needs to happen in the child class. I get an error:
传递给调用的参数不带参数
Argument passed to call that takes no arguments
我不确定如何在不复制并将其粘贴到每个子类中的情况下使其功能可用于其子类.
I'm not completely sure how to make the function available to it's child classes without copy and pasting it inside each child class.
这是父类:
class JSONObject: NSObject {
static func updateResultsDictionary(urlExtension: String, completion:
@escaping (JSONObject?) -> Void) {
let nm = NetworkManager.sharedManager
_ = nm.getJSONData(urlExtension: urlExtension) {data in
guard let jsonDictionary = nm.parseJSONFromData(data), let
resultDictionaries = jsonDictionary["result"] as?
[[String : Any]] else {
completion(nil)
return
}
for resultsDictionary in resultDictionaries {
let jsonInfo = JSONObject(resultsDictionary: resultsDictionary)// Here is where the error "Argument passed to call that takes no arguments" happens
completion(jsonInfo)
}
}
}
}
这是一个示例子类:
class AirBnBObject: JSONObject {
var airbnbUS: Int
var airbnbLocal: Int
init(airbnbUS: Int, airbnbLocal: Int){
self.airbnbUS = airbnbUS
self.airbnbLocal = airbnbLocal
}
init(resultsDictionary:[String: Any]){
guard let cost = resultsDictionary["cost"] as? [String: Any],
let airbnb = cost["airbnb_median"] as? [String : Any],
let usd = airbnb["USD"] as? Int,
let chf = airbnb["CHF"] as? Int
else {
airbnbUS = 0
airbnbLocal = 0
return
}
airbnbUS = usd
airbnbLocal = chf
}
}
推荐答案
我将转向使用协议而不是类,这样,您可以设计JSONObject来要求实现它的所有类也必须实现init(resultsDictionary:[String:Any]).这样,您就可以在协议扩展中编写updateResultsDictionary函数(这会导致任何实现的类也继承该函数).
I would move towards using a protocol instead of a class, that way you can design your JSONObject to require any classes that implement it to also implement init(resultsDictionary: [String:Any]). This allows you to write your updateResultsDictionary function in a protocol extension (which causes any implementing class to also inherit that function).
该协议如下所示:
protocol JSONObject: class, NSObjectProtocol {
init(resultsDictionary: [String:Any])
}
extension JSONObject {
static func updateResultsDictionary<T: JSONObject>(urlExtension: String, completion:
@escaping (_ jsonObject: T?) -> Void) {
let nm = NetworkManager.sharedManager
_ = nm.getJSONData(urlExtension: urlExtension) {data in
guard let jsonDictionary = nm.parseJSONFromData(data),
let resultDictionaries = jsonDictionary["result"] as? [[String : Any]] else {
completion(nil)
return
}
for resultsDictionary in resultDictionaries {
let jsonInfo = T(resultsDictionary: resultsDictionary)
completion(jsonInfo)
}
}
}
}
该函数必须通用,以避免您看到无法实例化协议类型"的错误.使用符合JSONObject而不是JSONObject本身的类T可以修复该错误.(请注意,使用T将是您的合格类,请参见下文)
The function needs to be generic in order to avoid the error you were seeing 'Protocol type cannot be instantiated'. Using class T which conforms to JSONObject rather than JSONObject itself fixes the error. (Note that in use T would be your conforming class, see below)
和任何实现类将如下所示:
and any implementing class would look something like this:
class AirBnBObject: NSObject, JSONObject {
var airbnbUS: Int
var airbnbLocal: Int
init(airbnbUS: Int, airbnbLocal: Int){
self.airbnbUS = airbnbUS
self.airbnbLocal = airbnbLocal
}
required init(resultsDictionary:[String: Any]){
guard let cost = resultsDictionary["cost"] as? [String: Any],
let airbnb = cost["airbnb_median"] as? [String : Any],
let usd = airbnb["USD"] as? Int,
let chf = airbnb["CHF"] as? Int
else {
airbnbUS = 0
airbnbLocal = 0
return
}
airbnbUS = usd
airbnbLocal = chf
}
}
要将扩展功能与此类一起使用,您需要这样做:
To use your extension function with this class you need to do it this way:
AirBnBObject.updateResultsDictionary(urlExtension: "") { (_ jsonObject: AirBnBObject?) -> Void in
print("update results dictionary")
}
这篇关于在父类上创建一个所有子类都可以访问的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!