当两个函数的名称和参数类型太相似时,Swift 会调用错误的函数吗?

问题描述 投票:0回答:1

我有两个函数,每个函数都有相同的名称。参数几乎相同,但一个函数引用特定类,而另一个函数引用该特定类的基类。当调用带有基类参数的第二个函数时,Swift 会对其进行编译以创建无限递归。它应该编译它以根据参数类型调用“正确”的函数(第一个)。在此代码中,请注意

Element
Spline
的基类。当 Spline 对象作为元素参数传递时,由于递归,对第二个底部函数的调用以崩溃结束:

func getArea( of spline: Spline, areaType: AreaType, scale: Scale ) -> Rect {
    let area = spline.getArea( areaType: areaType )
    if !area.isEmpty {
        let renderArea = scale.toDestination( from: area )
        if areaType == .selection {
            return renderArea.inflated( by: scale.toDestinationUnits( from: StaticDrawingParameters.controlKnobRadius ) * 2.0 )
        } else {
            return renderArea
        }
        //return renderArea
    }
    return area
}

func getArea( of element: Element, areaType: AreaType, scale: Scale ) -> Rect? {
    if let spline = element as? Spline {
        return getArea( of: spline, areaType: areaType, scale: scale )
    }
    return nil
}

当使用恰好是

Element
Spline
引用调用第二个函数时,它会正确地将
Element
转换为
Spline
引用(根据调试器),然后调用它所在的 getArea() 函数已经存在。它不使用其他 getArea() 函数,即使它有一个参数是
Spline
而不是
Element

我正在尝试找出我的错误或确定编译器无法正确处理此问题。

代码是这样设计的,因为我使用了需要处理的各种类型的

Element
对象的数组(为了清楚起见,我删除了其中的一些代码)。每个派生类型都派生自
Element
,并且每个派生类型的面积计算方式都不同。面积计算还涉及使用有关输出设备的信息(屏幕、打印机、某种奇怪的文本格式的文件等),因此数据对象本身不知道如何执行此操作。否则,这些将是各个元素类中的成员函数。

代码中是否有错误,或者我认为编译应该根据参数类型正确选择要调用的函数?

我将更改参数名称来解决此问题,但如果是我犯的错误导致了此问题,我宁愿修复它。

swift
1个回答
0
投票

首先,请不要这样做。如果您要使用继承,请使用继承:

class Element {
    func area(type: AreaType, scale: Scale) -> Rect? { nil }
}
class Spline: Element {
    override func area(type: AreaType, scale: Scale) -> Rect { ... }
}

但是您的解决方案不起作用的原因是它们实际上并不那么相似。它们有不同的返回类型。所以,鉴于这一行:

    return getArea( of: spline, areaType: areaType, scale: scale )

编译器此时需要一个

Rect?
。它寻找一个
getArea(of:areaType:scale:)
,返回一个
Rect?
,并且只有一个。您希望它对返回
Rect
的方法执行可选升级,但它并没有这样做。它已经找到了一个可以准确返回它想要的内容的方法。

您可以通过使签名实际匹配并返回样条线版本来解决此问题

Rect?
。但更好的解决方案是直接使用继承。那么可选促销就不含糊了。请注意,在我上面的继承中,
Spline.area
返回一个非可选值。由于
override
,促销变得明确。

(也就是说,我确实建议避免在 Swift 中进行类继承,并且通常更喜欢使用协议和结构来处理此类事情。但是继承确实有效。)

© www.soinside.com 2019 - 2024. All rights reserved.