Swift 泛型函数和子类。有人能解释这个编译错误吗?

Swift 泛型函数和子类。有人能解释这个编译错误吗?,swift,generics,compiler-errors,Swift,Generics,Compiler Errors,有人能解释一下为什么这个例子中的最后一个例子是编译错误吗 class A{} class B: A{} protocol Finder{ func find< T: A>(_ f: (T)->Bool) -> T? } class FinderImpl : Finder{ func find<T : A>(_ f: (T) -> Bool) -> T? { //In the real code I use

有人能解释一下为什么这个例子中的最后一个例子是编译错误吗

class A{}
class B: A{}

protocol Finder{
    func find< T: A>(_ f: (T)->Bool)  -> T?
}

class FinderImpl : Finder{
    func find<T : A>(_ f: (T) -> Bool)   -> T? {
        //In the real code I use T to find the instance. I.e. CoreData
        return nil
    }
}

let finder = FinderImpl()

//OK 
let optionalB : B? =  finder.find{_ in true}
let a : A =  finder.find{_ in true}!
let b : B =  finder.find{(b: B) in true}!

//Compile Error
let b2 : B =  finder.find{_ in true}!
class A{}
B类:A{}
协议查找器{
函数查找(f:(T)->Bool)->T?
}
类FinderImpl:Finder{
func find(f:(T)->Bool)->T{
//在实际代码中,我使用T来查找实例,即CoreData
归零
}
}
让finder=FinderImpl()
//嗯
让我们选择B:B=finder.find{intrue}
让a:a=finder.find{{uu}为真!
让b:b=finder.find{(b:b)in true}!
//编译错误
让b2:B=finder.find{intrue}!
让a.编译器使用
(a)->Bool.
作为闭包类型。那么返回类型是A

让b.之所以编译,是因为闭包有明确的信息:
(b)->Bool

让我们选择B。我想知道为什么这个案例有效,这里的结案也没有信息。区别在于
!操作员

错误:在最后一种情况下,编译器无法推断传递给func find的闭包类型。它建议我将
转换为!B
,因为它认为闭包类型是
(A)->Bool
。它没有使用b2 B的参考类型

重要提示:我不能将
转换为!B
因为我需要find函数来实际使用类型B。如果我将
强制转换为!B
,函数将使用类型A并获取错误的实例。代码可以编译,但结果可能是错误的

如果删除
T:A
限制,则不会出现编译错误。

在我看来,这像是一个编译器错误。我认为编译器应该使用b2类型来知道闭包是
(B)->Bool
,然后是find的结果类型。
T:A
限制和闭包中缺少类型信息导致它失败


我是不是遗漏了什么?有什么想法吗?

因为Swift无法推断上一个示例中的返回类型

在泛型函数中,您声明
T
必须是
A
A
的子类:

func find<T : A>(_ f: (T) -> Bool) -> T? {
    return nil
}
finder.find{ _ in true}! // this return A
             ^ what type is this? The compiler doesn't have any extra
               information so it must be A according to the declaration
在这里,您没有提供任何类型信息,因此编译器唯一依赖的是泛型函数的声明,它表示
T:A

finder.find{ _ in true}! // this return A
             ^ what type is this? The compiler doesn't have any extra
               information so it must be A according to the declaration
您可以通过进行显式转换将其提交给编译器:

let b2 : B =  finder.find{ _ in true}! as! B
或提供类型信息:

let b3 : B =  finder.find{ (_: B) in true}!

(这是为了让它只进行编译。代码在运行时显然会崩溃,因为您正在强制展开一个nil值)

因为Swift无法推断上一个示例中的返回类型

在泛型函数中,您声明
T
必须是
A
A
的子类:

func find<T : A>(_ f: (T) -> Bool) -> T? {
    return nil
}
finder.find{ _ in true}! // this return A
             ^ what type is this? The compiler doesn't have any extra
               information so it must be A according to the declaration
在这里,您没有提供任何类型信息,因此编译器唯一依赖的是泛型函数的声明,它表示
T:A

finder.find{ _ in true}! // this return A
             ^ what type is this? The compiler doesn't have any extra
               information so it must be A according to the declaration
您可以通过进行显式转换将其提交给编译器:

let b2 : B =  finder.find{ _ in true}! as! B
或提供类型信息:

let b3 : B =  finder.find{ (_: B) in true}!

(这是为了让它只进行编译。代码在运行时显然会崩溃,因为您正在强制展开一个nil值)

您好,谢谢您的回答。我理解你的观点,我想我在问题中也提到了这一点。我所看到的问题是,在let b2:B中,我实际上指定了类型信息。T=B。我不明白为什么还需要显式地声明(B)->Bool。以optionalB为例,我没有指定闭包类型,但它可以工作。这就是为什么我认为这可能是一个编译器错误。有什么想法吗?嗨,谢谢你的回答。我理解你的观点,我想我在问题中也提到了这一点。我所看到的问题是,在let b2:B中,我实际上指定了类型信息。T=B。我不明白为什么还需要显式地声明(B)->Bool。以optionalB为例,我没有指定闭包类型,但它可以工作。这就是为什么我认为这可能是一个编译器错误。有什么想法吗?