【问题标题】:Swift generic function does not compile in testingSwift 泛型函数在测试中无法编译
【发布时间】:2016-06-14 07:12:48
【问题描述】:

我在 Swift 中编译测试用例时遇到问题。看起来编译器正在丢失有关模板类型的信息,但其他通用方法工作正常。我错过了什么?

public class MatchNorm {

    public static func resolve1<T:SequenceType where T.Generator.Element:MatchNormElement>(list: T, lti: LinearTransformation, accuracy: Double) -> LinearTransformation {
        // no problem
        return MatchNorm.resolve1(list, lti: lti, accuracy: accuracy)
    }

    public static func resolve2<T:SequenceType where T.Generator.Element:MatchNormElement>(list: T, lti: LinearTransformation, accuracy: Double) -> LinearTransformation {

        for elem in list {
            print(elem.x)
        }
        return lti
    }
}
public class MatchNormTest: XCTestCase  {
    func testMatchNorm1() {
        var list = [MatchNormElement]()

        // compilation error here!
        let  ll = MatchNorm.resolve1(list, lti: LinearTransformation(1), accuracy: 0.001)
// MatchNormTest.swift:70:29: Cannot invoke 'resolve1' with an argument list of type '([MatchNormElement], lti: LinearTransformation, accuracy: Double)'
// MatchNormTest.swift:70:29: Expected an argument list of type '(T, lti: LinearTransformation, accuracy: Double)'
    }
}

更新

MatchNormElement 是一个协议,所以我将其更改为具体类型。现在可以了。

func testMatchNorm1() {
    var list = [Measurment]()

        // works fine
     let  ll = MatchNorm.resolve1(list, lti: LinearTransformation(1), accuracy: 0.001)
}

【问题讨论】:

  • 我用NSString替换了MatchNormElementLinearTransformation(并删除了resolve2,这个方法不需要找问题),没有编译错误。也许这些信息会对您有所帮助。
  • 感谢 ShadowOf。 MatchNormElement 是一个协议。看起来列表必须是具体类型。

标签: xcode swift generics xctest


【解决方案1】:

这对编译器来说是合理的。 Swift 允许将具体类型的类型转换为基于协议的变量赋值。

但是,Swift 不允许通过转换每个具体类型将一组具体类型转换为协议的集合/数组。这是合理的,原因如下:

假设我们有这个结构:

protocol IntType {}
extension Int: IntType{}

现在让我们做一件显而易见的事情:

let item = 12
let item2:IntType = item

然后看起来很明显:这不会编译有充分的理由。

let a = [1,2,3]
let b: [IntType] = a

让我们在继续之前检查每个类型的大小:

sizeofValue(item)   //8
sizeofValue(item2)  //40

数组是 8 字节的传染性内存。 Array 也是 40 字节的传染性内存。

当我们这样做时:

let b: [IntType] = a

我们基本上告诉编译器将 8 字节数组转换为 40 字节数组并存储它。 现在由于数组具有传染性,它必须破坏或重新洗牌,这是一项昂贵的任务。这会阻碍性能,显然您会失去类型安全性。

编译器可以进行这种转换,但 Swift 团队有充分的理由认为,如果用户想要这种类型转换,则需要明确说明,原因有两个:性能类型安全.

【讨论】:

    猜你喜欢
    • 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
    相关资源
    最近更新 更多