从协议作为参数调用类方法

时间:2014-09-24 20:09:54

标签: class generics swift class-method

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

我正在使用Swift,并且有一个像这样定义的协议

    //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)
    }

实现协议的对象

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'
  }

}

然而,我一直收到两个错误。我已用'&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;

编译错误。

2 个答案:

答案 0 :(得分:2)

这里要考虑很多小事,但让我们深入到你的问题的核心。您想要的签名如下所示:

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

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

我建议你的协议如下:

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

通过这种方式,您承诺退回自己的课程,而不仅仅是任何可以解析的课程。这确实意味着您需要制作课程final。如果您不希望它们为final,则您需要承诺一些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")

答案 1 :(得分:1)

我只想指出,您确切问题的答案是声明您的功能:

func getSomeParsingDone(model:FAUAPIModel.Type? = nil, getPath:path) -> FAUAPIModel