不能明确地专门化一个generics函数

我有以下代码的问题:

func generic1<T>(name : String){ } func generic2<T>(name : String){ generic1<T>(name) } 

通用1(名称)结果编译器错误“不能明确地专门化通用函数”

有什么办法可以避免这个错误? 我不能改变generic1函数的签名,所以它应该是(String) – > Void

我也有这个问题,我发现我的情况的解决方法。

在这篇文章中,作者有同样的问题

https://www.iphonelife.com/blog/31369/swift-programming-101-generics-practical-guide

所以问题似乎是,编译器需要以某种方式推断T的types。 但不允许简单地使用generics<type>(params …)。

通常情况下,编译器可以通过扫描参数types来查找T的types,因为这在很多情况下是使用T的地方。

在我的情况下,它有点不同,因为我的函数的返回types是T.在你的情况下,似乎你没有在你的函数中使用T. 我想你只是简化了示例代码。

所以我有以下function

 func getProperty<T>( propertyID : String ) -> T 

而在,例如

 getProperty<Int>("countProperty") 

编译器给了我

 Cannot explicitly specialize a generic function 

所以,为了给编译器提供另一个信息来源来推断T的types,你必须显式地声明返回值保存的variables的types。

 var value : Int = getProperty("countProperty") 

这样编译器知道T必须是一个整数。

所以我认为总的来说,它只是意味着如果你指定一个generics函数,你至less必须在你的参数types中使用T或者作为返回types。

解决scheme是将类types作为参数(如在Java中)

让编译器知道他正在处理什么types的类作为参数

 extension UIViewController { func navigate<ControllerType: UIViewController>(_ dump: ControllerType.Type, id: String, before: ((ControllerType) -> Void)?){ let controller = self.storyboard?.instantiateViewController(withIdentifier: id) as! ControllerType before?(controller) self.navigationController?.pushViewController(controller, animated: true) } } 

呼叫:

 self.navigate(UserDetailsViewController.self, id: "UserDetailsViewController", before: { controller in controller.user = self.notification.sender }) 

Swift 3.1

通常有很多方法来定义generics函数。 但它们是基于T必须用作parameter或作为return type

 extension UIViewController { class func doSomething<T: UIView>() -> T { return T() } class func doSomethingElse<T: UIView>(value: T) { // Note: value is a instance of T } class func doLastThing<T: UIView>(value: T.Type) { // Note: value is a MetaType of T } } 

之后,我们必须在打电话时提供T

 let result = UIViewController.doSomething() as UIImageView // Define `T` by casting, as UIImageView let result: UILabel = UIViewController.doSomething() // Define `T` with property type, as UILabel UIViewController.doSomethingElse(value: UIButton()) // Define `T` with parameter type, as UIButton UIViewController.doLastThing(value: UITextView.self) // Define `T` with parameter type, as UITextView 

参考:

  1. http://austinzheng.com/2015/01/02/swift-generics-pt-1/
  2. https://dispatchswift.com/type-constraints-for-generics-in-swift-d6bf2f0dbbb2

你不需要generics,因为你有静态types(String作为参数),但是如果你想有一个generics函数调用另一个,你可以执行以下操作。

使用通用方法

 func fetchObjectOrCreate<T: NSManagedObject>(type: T.Type) -> T { if let existing = fetchExisting(type) { return existing } else { return createNew(type) } } func fetchExisting<T: NSManagedObject>(type: T.Type) -> T { let entityName = NSStringFromClass(type) // Run query for entiry } func createNew<T: NSManagedObject>(type: T.Type) -> T { let entityName = NSStringFromClass(type) // create entity with name } 

使用generics类(不太灵活,因为generics只能针对每个实例的1种types定义)

 class Foo<T> { func doStuff(text: String) -> T { return doOtherStuff(text) } func doOtherStuff(text: String) -> T { } } let foo = Foo<Int>() foo.doStuff("text") 

我认为当你指定generics函数时,你应该指定一些typesT的参数,如下所示:

 func generic1<T>(parameter: T) { println("OK") } func generic2<T>(parameter: T) { generic1(parameter) } 

如果你想调用handle()方法,那么你可以通过编写协议来做到这一点,并指定T的types约束:

 protocol Example { func handle() -> String } extension String: Example { func handle() -> String { return "OK" } } func generic1<T: Example>(parameter: T) { println(parameter.handle()) } func generic2<T: Example>(parameter: T) { generic1(parameter) } 

所以你可以用String来调用这个generics函数:

 generic2("Some") 

它会编译

我有一个类似的问题,我的generics类函数class func retrieveByKey<T: GrandLite>(key: String) -> T?

我无法调用它let a = retrieveByKey<Categories>(key: "abc")其中Categories是GrandLite的子类。

let a = Categories.retrieveByKey(key:"abc")返回GrandLite,而不是Categories。 通用函数不会根据调用它们的类来推断types。

class func retrieveByKey<T: GrandLite>(aType: T, key: String>) -> T? 当我尝试let a = Categories.retrieveByKey(aType: Categories, key: "abc")给了我一个错误,它无法将Categories.Type转换为GrandLite,即使类别是GrandLite的子类。 然而…

class func retrieveByKey<T: GrandLite>(aType: [T], key: String) -> T? 如果我尝试let a = Categories.retrieveByKey(aType: [Categories](), key: "abc")看起来显然是一个子类的显式分配不起作用,但使用另一个genericstypes(数组)的隐式分配确实工作在Swift 3。