Swift:函数返回一个IntegerType数组

时间:2014-10-21 05:12:56

标签: swift generics

我想创建一个带有NSData参数的函数,并根据它从NSData读取的内容返回Array<Int8>Array<Int16>,{ {1}}或Array<Int32>

基本上,我需要返回一个Array<Int64>数组,并在运行时确定特定的子类型。

我被困在函数的签名声明中。 (内部只是一个简单的开关,它将创建特定的数组类型并返回它。)

以下非常基本的测试无法编译

IntegerType

修改

目前似乎不可能,不是因为必须返回协议类型的数组,而是因为IntegerType协议使用class Test { func test(data:NSData) -> Array<IntegerType> { return [1, 2, 3] } } 。这是一个有趣的相关question

5 个答案:

答案 0 :(得分:0)

IntegerType是一个协议,因此以下内容应该有效:

class Test {
    func test(data:NSData) -> Array<T: IntegerType> {
      [1, 2, 3]
    }
}

答案 1 :(得分:0)

您可以使用enum with associated values

enum IntArray {
    case Int8([Swift.Int8])
    case Int16([Swift.Int16])
    case Int32([Swift.Int32])
    case Int64([Swift.Int64])
}


class Test {
    func test(data:NSData) -> IntArray {
        return IntArray.Int8([1, 2, 3]);
    }
}
用户方

let obj = Test()
let array = obj.test(dat)

switch array {
case .Int8(let ary):
    // here, ary is [Int8]
    ...
case .Int16(let ary):
    // here, ary is [Int16]
    ...
case .Int32(let ary):
    // here, ary is [Int32]
    ...
case .Int64(let ary):
    // here, ary is [Int64]
    ...
}

答案 2 :(得分:0)

正如其他人在评论中所说的那样,如果你试图在运行时确定函数的返回类型,这将不起作用。 Swift泛型仅在编译时工作,因此根据NSData中的内容更改返回类型将无法正常工作。

如果你可以在编译时确定返回类型,那么你可以像这样使用generic function声明:

func test<T: IntegerType>(data: NSData) -> Array<T> {
    return [1, 2, 3]
}

注意:如果您不以某种方式在函数中明确指定类型,那么您需要定义从函数返回的值所赋予的变量。像这样:

var int8Array: Array<Int8> = test(NSData())

答案 3 :(得分:0)

由于基于通用的解决方案都不起作用,为什么不尝试返回[Any]并按如下方式检查返回类型: -

func test(data:NSData) -> [Any]
{
    var value1:Int8 = 1
    var value2:Int8 = 2
    return [value1,value2]
}

var x = test(NSData())
for xin in x
{
    var intxin = xin as? Int8
    if intxin != nil
    {
        println(intxin!)
    }
}

答案 4 :(得分:0)

我解决问题的方法是定义以下协议:

protocol IntegerArrayProtocol {
    init(rawData: NSData!, length: Int)

    func count() -> Int

    subscript(index:Int) -> Int { get }
}

这涉及我需要在阵列上执行的所有操作:

  1. 从原始内存中读取
  2. 计算它有多少元素
  3. 按索引访问其元素,始终返回Int s,无论基础整数如何 输入
  4. 然后,我创建了一个实现协议的参数化类:

    final class IntegerArray<T: ConvertibleToInteger>: IntegerArrayProtocol {
        let arr: [T]
    
        init(rawData: NSData!, length: Int){
            //create array and allocate memory for all elements
            arr = Array<T>(count: length, repeatedValue: T.zero())
    
            // read it from the NSData source
            // ....
        }
    
        func count() -> Int{
            return arr.count
        }
    
        subscript(index:Int) -> Int {
            get {
                return arr[index].asInt()
            }
        }
    }
    

    参数类型T应该能够将自身转换为Int,并且应该具有zero值(在初始化数组时使用)。为此,我创建了ConvertibleToInteger协议,上面用它来限制可能的T

    protocol ConvertibleToInteger {
       class func zero() -> Self
       func asInt() -> Int
    }
    

    然后,我扩展了我想要创建数组的所有类型:

    extension Int8: ConvertibleToInteger{
        static func zero() -> Int8{
            return 0
        }
        func asInt() -> Int{
            return Int(self)
        }
    }
    
    extension Int16: ConvertibleToInteger{
        static func zero() -> Int16{
            return 0
        }
        func asInt() -> Int{
            return Int(self)
        }
    }
    
    extension Int32: ConvertibleToInteger{
        static func zero() -> Int32{
            return 0
        }
        func asInt() -> Int{
            return Int(self)
        }
    }
    
    extension Int64: ConvertibleToInteger{
        static func zero() -> Int64{
            return 0
        }
        func asInt() -> Int{
            return Int(self)
        }
    }
    

    最后,为了从NSData读取数组,我创建了以下函数:

    func readArray(rawData: NSData, length: Int): IntegerArrayProtocol? {
        qBytes = // read from NSData how many bytes each element is
    
        switch(qBytes){
          case 1:
              return IntegerArray<Int8>(rawData: rawData, length: length)
          case 2:
              return IntegerArray<Int16>(rawData: rawData, length: length)
          case 3 ... 4:
              return IntegerArray<Int32>(rawData: rawData, length: length)
          case 5 ... 8:
              return IntegerArray<Int64>(rawData: rawData, length: length)
          default:
              return nil
        }
    }