【问题标题】:"Ambiguos use of function" when overloading a generic function in Swift在 Swift 中重载泛型函数时的“函数使用不明确”
【发布时间】:2016-04-19 14:40:30
【问题描述】:

您将在下面看到一个我试图说明我的问题的操场。我有一个类 (Foo) 有一些重载的泛型方法 (bar<T>()),其返回类型取决于泛型参数。我有 3 种方法:

  • 必须返回特定类型的子类(在下面的示例中称为BaseClass
  • 其他人必须返回此特定类型实例的Array
  • 如果不满足其他两个条件,则最后一个应用作默认值。

当我调用该方法时,问题就来了。即使我告诉编译器我期望的类型是什么,它也会给我错误Ambiguos use of bar()

import UIKit

class BaseClass {
    required init() {}
}

class Foo {

    // 1
    func bar<T: BaseClass>() -> T? {
        // Just a default implementation, it should do real work inside
        return T()
    }

    // 2
    func bar<T: BaseClass>() -> [T]? {
        // Just a default implementation, it should do real work inside
        return []
    }

    // 3
    func bar<T>() -> T? {
        // Just a default implementation, it should do real work inside
        return "Test" as? T
    }
}

let foo = Foo()

// Should call "1", because it return type is BaseClass
let baseClassObject: BaseClass? = foo.bar()

// Should call "2", because it return type is [BaseClass]
let baseClasArray: [BaseClass]? = foo.bar()

// Should call "3", because it return type is neither BaseClass nor [BaseClass]
let anyOtherObject: String = foo.bar()

在我看来,编译器应该知道什么方法调用,因为我告诉它返回类型,对吧?这是泛型的限制还是我遗漏了什么?

提前致谢。

4 月 19 日更新

在回答中,他们说发生冲突是因为“BaseClass”可以解释为BaseClass,也可以解释为T。但是在这个修改后的游乐场中,编译器确实会推断出正确使用哪种方法。有什么区别吗?我应该在这里有同样的冲突吗?:

import UIKit

class BaseClass {
    required init() {}
}

class Foo {

    // 1
    func bar<T: BaseClass>(param: T) -> String {
        return "I am BaseClass"
    }

    // 2
    func bar<T: BaseClass>(param: [T]) -> String {
        return "I am [BaseClass]"
    }

    // 3
    func bar<T>(param: T) -> String {
        return "I am other thing"
    } 
}

let foo = Foo()

// It prints "I am BaseClass"
foo.bar(BaseClass())

// It prints "I am [BaseClass]"
foo.bar([BaseClass(), BaseClass()])

// It prints "I am another thing"
foo.bar(NSObject())

【问题讨论】:

    标签: swift generics overloading


    【解决方案1】:

    数字 3 导致与其他功能冲突

    这是因为 也可以是 BaseClass 类型和 [BaseClass] 类型。编译器只会看到一个“将任何东西扔在这里”的接口,这将与任何更具体的特异性级别发生冲突。

    【讨论】:

    • 要扩展这个,let baseClassObject: BaseClass? = foo.bar()为什么要自动调用第一个bar
    • 是的,我知道冲突来自最后一个。我认为编译器知道我调用第一个是因为返回类型。我认为编译器从更具体到不太具体进行检查,并使用更具体的。至少,在其他情况下是这样的。请@PEEJWEEJ,查看我的问题更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多