【问题标题】:Cannot invoke 'methodName' with an argument list of type无法使用类型的参数列表调用“methodName”
【发布时间】:2016-09-21 17:47:29
【问题描述】:

我无法理解此编译器错误消息的重点 “无法使用类型为“(值:T)”的参数列表调用“getValueType” 对于“if (CMFStream.getValueType(value: test) != type) {”这一行

public func readArray<T>() -> Array<T>
{
    // ...
    var retval: Array<T>;
    let test: T;
    if (CMFStream.getValueType(value: test) != type) {
    // ...
    }
}

我想我不明白泛型和模板之间的区别。

【问题讨论】:

    标签: swift generics


    【解决方案1】:

    您将T 类型的对象传递给getValueType。 T 是不受约束的泛型类型,这意味着在编译时它可以是范围内已知的任何类型。它有一个明确的类型,但编译器不知道该类型是什么。 T 是它的占位符。

    当它遇到使用T 类型的参数调用getValueType 的行时,它会寻找一种方法来满足它。您看到的错误表明它没有找到解决方法。

    这是一个最小的例子:

    func foo<U>(f:U) {
        bar(b:f)
    }
    
    func bar(b:Int) {
    }
    

    这失败了,因为 bar 接受一个 Int,但 foo 可以将它传递给任何类型。

    有两种方法可以解决此问题。

    方法一

    使栏通用:

    func bar<V>(b:V) {
    }
    

    所以如果你打电话

    foo(f:1)
    

    编译器将U替换为Int,创建:

    func foo(f:Int) {
        bar(b:f)
    }
    

    现在它需要一个接受Int 的栏,因此它将V 替换为Int 来给出

    func bar(b:Int) {
    }
    

    现在类型是一致的,所以它可以继续。

    方法二

    约束U:

    protocol P {}
    
    func foo<U:P>(f:U) {
        bar(b:f)
    }
    

    这表示U 是任何符合P 协议的类型。所以现在我们可以像这样定义bar:

    func bar(b:P) {
    }
    

    这定义了一个bar,它接受任何符合协议P的东西。

    现在无论占位符U 被替换为什么,编译器都知道它符合P,并且它总能找到一个接受符合P 的内容的bar。编译器可以继续。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      相关资源
      最近更新 更多