无法明确专门化泛型函数

Gre*_*isf 81 generics swift

我有以下代码的问题:

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

func generic2<T>(name : String){
     generic1<T>(name)
}
Run Code Online (Sandbox Code Playgroud)

generic1(名称),结果到编译器错误"无法明确专门的通用功能"

有什么办法可以避免这个错误吗?我无法更改generic1函数的签名,因此它应该是(String) - > Void

Tho*_*ief 140

我也有这个问题,我找到了解决方法.

在本文中,作者有同样的问题

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

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

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

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

所以我有以下功能

func getProperty<T>( propertyID : String ) -> T
Run Code Online (Sandbox Code Playgroud)

例如,如果是的话

getProperty<Int>("countProperty")
Run Code Online (Sandbox Code Playgroud)

编译器给了我

Cannot explicitly specialize a generic function
Run Code Online (Sandbox Code Playgroud)

因此,为了给编译器提供另一个信息源来推断T的类型,你必须显式地声明保存返回值的变量的类型.

var value : Int = getProperty("countProperty")
Run Code Online (Sandbox Code Playgroud)

这样编译器就知道T必须是整数.

所以我认为总的来说它只是意味着如果你指定一个泛型函数,你必须至少在参数类型中使用T或作为返回类型.

  • 如果没有返回值,有没有办法做到这一点?即,`func updateProperty <T>(propertyID:String)` (3认同)
  • 节省了我很多时间.谢谢. (2认同)
  • 我不明白你为什么要这么做?由于您不返回任何内容,因此将函数声明为通用函数没有任何好处。 (2认同)

nah*_*g89 36

Swift 4.2

通常,有许多方法可以定义泛型函数.但它们是基于T必须用作a parameter或a的条件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
    }
}
Run Code Online (Sandbox Code Playgroud)

在那之后,我们必须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
Run Code Online (Sandbox Code Playgroud)

参考:

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


Ork*_*nov 19

解决方案是将类类型作为参数(如在Java中)

让编译器知道他正在处理什么类型将类作为参数传递

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

呼叫:

self.navigate(UserDetailsViewController.self, id: "UserDetailsViewController", before: {
        controller in
        controller.user = self.notification.sender
    })
Run Code Online (Sandbox Code Playgroud)


ary*_*axt 5

这里不需要泛型,因为您有静态类型(字符串作为参数),但如果您想让泛型函数调用另一个泛型函数,您可以执行以下操作。

使用通用方法

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
} 
Run Code Online (Sandbox Code Playgroud)

使用泛型类(不太灵活,因为泛型只能为每个实例定义一种类型)

class Foo<T> {

   func doStuff(text: String) -> T {
      return doOtherStuff(text)
   }

   func doOtherStuff(text: String) -> T {

   }  

}

let foo = Foo<Int>()
foo.doStuff("text")
Run Code Online (Sandbox Code Playgroud)


Val*_*der 4

我认为当你指定泛型函数时,你应该指定一些 T 类型的参数,如下所示:

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

func generic2<T>(parameter: T) {
    generic1(parameter)
}
Run Code Online (Sandbox Code Playgroud)

如果你想调用handle()方法,那么你可以通过编写协议并为T指定类型约束来实现:

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)
}
Run Code Online (Sandbox Code Playgroud)

所以你可以用字符串调用这个通用函数:

generic2("Some")
Run Code Online (Sandbox Code Playgroud)

它会编译