不能明确地专门化一个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
参考:
你不需要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。