Skip to main content
 首页 » 操作系统

class之从协议(protocol)调用类方法作为参数

2024年01月01日36rubylouvre

我希望能够将某个协议(protocol)类型的类(不是初始化对象)传递给一个方法,然后在方法中调用该类的类函数。代码如下。

我正在使用 Swift 并且有一个这样定义的协议(protocol)

    //Protocol for any object to be used with an FAUAPIConnection 
protocol FAUAPIModel{ 
 
    //Used to parse the object from a given dictionary to an object 
    class func parseFromJSON(JSON:AnyObject) -> Self 
 
    //Required default init 
    init() 
 
} 

我想做的就是有这样的方法

    func getSomeParsingDone<T:FAUAPIModel>(model:T.Type? = nil, getPath:path, callingObj:CallingClass) -> Void 
    { 
        //GetIt is inconsequential, just logic to get an object from a certain path 
         var returnObj:AnyObject = GetIt.get(path) 
         if(model != nil){ 
            returnObj = model!.parseFromJSON()  <<<<<< Type 'T' does not conform to protocol 'AnyObject' 
         } 
         callingObj.done(returnObj) 
    } 

实现协议(protocol)的对象

import Foundation 
 
class MyObj: FAUAPIModel{   
 
   var neededVal:String 
   var nonneededVal:String 
 
  required convenience init(){ 
    self.init(neededVal:"VALUE") 
  } 
 
  init(neededVal:String, nonneededVal:String = ""){ 
    self.neededVal = neededVal 
    self.nonneededVal = nonneededVal 
  } 
 
  class func parseFromJSON(JSON:AnyObject) -> WGMPart 
  { 
     return WGMPart() <<<<<<<< Method 'parseFromJSON' in non-final class 'WGMPart' must return 'Self' to conform to protocol 'FAUAPIModel' 
  } 
 
} 

但是,我不断收到两个错误。我在上面用 '<<<<<<<<<<<<'

指出了这些

编译错误。

请您参考如下方法:

这里有很多小事需要考虑,但让我们直奔问题的核心。您想要的签名如下所示:

func getSomeParsingDone<T:FAUAPIModel>(model:T.Type, path:String) -> T? 

我将 return 设为可选,因为这里有很多事情可能会失败,你真的不应该把所有这些都变成崩溃。

我建议您的协议(protocol)如下所示:

protocol FAUAPIModel { 
    class func parseFromJSON(JSON:AnyObject) -> Self 
} 

这样,您就可以保证返回自己的类,而不仅仅是任何可解析的类。这确实意味着您需要将您的类设置为 final。如果你不希望它们是final,你需要 promise 一些init方法来构造它。参见 Protocol func returning Self了解有关如何在需要时处理该问题的更多详细信息。

所以把它放在一起,在实践中可能看起来像这样:

protocol FAUAPIModel { 
  class func parseFromJSON(JSON:AnyObject) -> Self 
} 
 
func createObjectOfClass<T: FAUAPIModel>(model: T.Type, path: String) -> T? { 
  if let json: AnyObject = GetJSON(path) { 
    return model.parseFromJSON(json) 
  } 
  return nil 
} 
 
// Bogus JSON reader 
func GetJSON(path: String) -> AnyObject? { 
  let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(path.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!, options: NSJSONReadingOptions(0), error: nil) 
  return json 
} 
 
// Bogus model class that returns trivial version of itself 
final class Something: FAUAPIModel { 
  class func parseFromJSON(JSON:AnyObject) -> Something { 
    return Something() 
  } 
} 
 
// Using it 
let something = createObjectOfClass(Something.self, "/path/to/file")