在父类上创建一个所有子类都可以访问的函数 [英] Creating a function on a parent class that can be accessible to all it's child classes

查看:53
本文介绍了在父类上创建一个所有子类都可以访问的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在其子类可以访问的父类中创建一个函数.我遇到的问题是该功能的一部分,它是指需要在子类中发生的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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆