通用参数T无法推断。工厂方法 [英] Generic parameter T could not be inferred. Factory methods

查看:85
本文介绍了通用参数T无法推断。工厂方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个工厂方法的类,如下所示:

  public class NetworkTask< T> {

var request:URLRequest

var completionHandler:NetworkResponse< T> - > void

init(request:URLRequest,completionHandler:NetworkResponse< T> - > Void){

self.request =请求
self.completionHandler = completionHandler
}

static func dataResponseTaskWithRequest(request:URLRequest,completionHandler:NetworkResponse< NSData> - > Void) - > NetworkTask< NSData的> {

return NetworkTask< NSData>(request:request,completionHandler:completionHandler)
}

static func mappedObjectResponseTaskWithRequest< MappedType>(request:URLRequest,completionHandler:NetworkResponse< ; MappedType> - > Void) - > NetworkTask< MappedType> {

return NetworkTask< MappedType>(request:request,completionHandler:completionHandler)
}
}

然后,在快乐地知道它编译完成之后,我去创建一个这样的任务:

  let task = NetworkTask.dataResponseTaskWithRequest(URLRequest()){(response)in 

}

$ b $


通用参数T无法推断
/ blockquote>

等等,我可以清楚地推断出,该方法返回 NetworkTask< NSData> ,所以T是NSData。 p>

好吧...那么,也许这样?

  let task: NetworkTask< NSData的> = NetworkTask.dataResponseTaskWithRequest(URLRequest()){(response)in 

}

无法...


无法使用类型为'(URLRequest,(_) - > _)的参数列表调用'dataResponseTaskWithRequest' '

好的,也许另一种方法:

 

$ b 让task = NetworkTask.mappedObjectResponseTaskWithRequest(URLRequest()){(response:NetworkResponse< String>)






不能将类型'(NetworkResponse) - >()'到期望的
参数类型'NetworkResponse< _> - > Void'

我必须明显缺少这里的东西,因为编译器不能有这么多的错误。是否有人有任何线索?

解决方案

NetworkTask< T> 类型,而不是 NetworkTask 。也就是说,参数 T 在类上,你使用这个类做的所有事情,也要访问它的类方法,都需要描述这个类型。

尽管 T 没有包含在方法声明中,但是它给出了编译器错误,没有类 NetworkTask 将包含所有不包含类型参数的类方法 - 假设方法在所有类上 NetworkTask< T> code>为任何值 T 。这与C ++类似,其中相应的甚至被称为模板,这意味着您的具有泛型类型参数的类声明被用作从字面上编译不同类的模板。这与Java的不同之处在于,泛型语法只是在类型擦除时编译时间糖(您确实可以调用类方法 - 在这种情况下,实际上只存在一个类)。



下面是一个简单的例子来演示这一点:

  class A< T> {
class func foo(){
}

class func bar(t:T) - >无效{
}
}

class B {}

A.foo()//这样会产生错误,因为无法推断类型。

A.bar(1)//这个工作正常,没有编译错误,因为整型文字类型可以在那里被推断。

在上面的示例中,A可以很好地调用实例:



A< IntegerLiteralType> .foo()



这种情况下的方法是否属于类型参数为 T 的类,或者它们是否应该有别的东西作为接收者(或者实际上它们是否应该是自由函数? )。


Can someone explain to me why this wouldn't work?

I have a class with factory methods like this:

public class NetworkTask<T> {

    var request: URLRequest

    var completionHandler: NetworkResponse<T> -> Void

    init(request: URLRequest, completionHandler: NetworkResponse<T> -> Void) {

        self.request = request
        self.completionHandler = completionHandler
    }

    static func dataResponseTaskWithRequest(request: URLRequest, completionHandler: NetworkResponse<NSData> -> Void) -> NetworkTask<NSData> {

        return NetworkTask<NSData>(request: request, completionHandler: completionHandler)
    }

    static func mappedObjectResponseTaskWithRequest<MappedType>(request: URLRequest, completionHandler: NetworkResponse<MappedType> -> Void) -> NetworkTask<MappedType> {

        return NetworkTask<MappedType>(request: request, completionHandler: completionHandler)
    }
}

Then, after happily knowing that it compiles, I go to create a Task like this:

let task = NetworkTask.dataResponseTaskWithRequest(URLRequest()) { (response) in

    }

Nope...

Generic parameter T could not be inferred

Wait, I can clearly infer it, the method returns NetworkTask<NSData>, so T is NSData.

Ok... then, maybe like this?

let task: NetworkTask<NSData> = NetworkTask.dataResponseTaskWithRequest(URLRequest()) { (response) in

}

Nope...

Cannot invoke 'dataResponseTaskWithRequest' with an argument list of type '(URLRequest, (_) -> _)'

Ok, so maybe the other method:

let task = NetworkTask.mappedObjectResponseTaskWithRequest(URLRequest()) { (response: NetworkResponse<String>) in

}

Nope...

Cannot convert value of type '(NetworkResponse) -> ()' to expected argument type 'NetworkResponse<_> -> Void'

I must be clearly missing something here because the compiler can't have so many errors. Does anybody have any clue?

解决方案

NetworkTask<T> is the type, not NetworkTask. That is, the parameter T is on the class and everything you do with that class, also to access its class methods, require describing that type.

Even though the T is not included in the method declaration that gives you the compiler error, there is no class NetworkTask that would contain all the class methods where the type parameter is not included – imagine instead that the method is on all classes NetworkTask<T> for any value of T. This is similar to C++ where the corresponding is even called "template", meaning that your class declaration with generic type parameters is used as a template for literally compiling different classes. This is different to for instance Java where the generics syntax is just compile time sugar with type erasure (you could indeed there call the class method – only one class really exists in that case).

Here's a minimal example to demo this some more:

class A<T> {
    class func foo() {
    }

    class func bar(t:T) -> Void {
    }
}

class B {}

A.foo() // this gives an error because the type cannot be inferred.

A.bar(1) // this works fine without compiler errors as the integer literal type can be inferred there.

In the example case above, A would be fine to called for instance with:

A<IntegerLiteralType>.foo()

You should perhaps consider whether the methods in this case belong in the class that has that type parameter T, or whether they should have something else as a receiver (or indeed whether they should be free functions?).

这篇关于通用参数T无法推断。工厂方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆