Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift:返回IntegerType数组的函数_Swift_Generics - Fatal编程技术网

Swift:返回IntegerType数组的函数

Swift:返回IntegerType数组的函数,swift,generics,Swift,Generics,我想创建一个接受NSData参数的函数,并根据从NSData读取的内容返回数组、数组、数组或数组 基本上,我需要返回IntegerType数组,具体的子类型在运行时确定 我被函数的签名声明卡住了。内部只是一个简单的开关,它将创建特定的数组类型并返回它 以下非常基本的测试无法编译 class Test { func test(data:NSData) -> Array<IntegerType> { return [1, 2, 3] } } 编辑 目前

我想创建一个接受NSData参数的函数,并根据从NSData读取的内容返回数组、数组、数组或数组

基本上,我需要返回IntegerType数组,具体的子类型在运行时确定

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

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

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

目前似乎不可能,不是因为必须返回协议类型的数组,而是因为IntegerType协议使用Self。下面是一个有趣的相关

IntegerType是一个协议,因此以下内容应该可以工作:

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

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]
    ...
}

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

如果可以在编译时确定返回类型,则可以使用如下声明:

func test<T: IntegerType>(data: NSData) -> Array<T> {
    return [1, 2, 3]
}
注意:如果您没有以某种方式在函数中显式指定类型,那么您需要定义从函数返回的值分配给的变量。像这样:

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

既然所有基于泛型的解决方案都不起作用,为什么不尝试返回[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!)
    }
}

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

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

    func count() -> Int

    subscript(index:Int) -> Int { get }
}
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()
        }
    }
}
这将处理我需要在阵列上执行的所有操作:

从原始内存中读取它 数一数它有多少元素 通过索引访问其元素,始终返回整数,而不考虑基础整数 类型 然后,我创建了一个实现协议的参数化类:

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

    func count() -> Int

    subscript(index:Int) -> Int { get }
}
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()
        }
    }
}
然后,我扩展了要创建数组的每种类型:

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
    }
}

是的,它给了我一个“0”没有成员“Element”错误您使用的是哪个版本的Swift?它使用Xcode->About Xcode Version 6.0.1 for iOSOh报告的版本6.1 6A1030为我编译。我现在看到,您在最初发布后就编辑了代码——我上面提供的函数签名有效,但尝试从函数返回值确实会产生上面识别的错误Rajeev Bhatia。我想得越多,就越不相信您所尝试的是可能的:定义一个返回值为泛型的函数,其实际类型由函数的实现决定,而不是由其输入参数的类型决定。我想不出一个现有的例子。你能吗?我想弄明白他为什么要这么做,尤其是对Int,因为苹果明确主张使用通用Int类型而不是特定类型。你为什么要这样做?苹果官方文档本身要求您对任何整数大小使用Int一致使用Int有助于代码互操作性,避免在不同的数字类型之间转换,并匹配整数类型推断基本上,我需要返回IntegerType数组,在运行时确定特定的子类型。-不可能。推断类型将在编译时确定。基本方法应该始终是泛型的,或者尽可能使用Int作为通用类型。在泛型数组中,T表示占位符类型名称。当一个类型(比如数组)将被实例化时,T必须替换为一个类型。IntegerType不是类型,它是协议。@Eduardo您假设泛型函数参数和泛型返回值之间不存在并行性。请考虑一下:如何声明一个变量来存储函数的返回值?必须在编译时知道类型以分配存储,但在运行时之前无法知道返回值的实际类型。在编译时,您只知道它符合IntegerType协议。问题是,我以后对IntArray做不了什么。我需要一个能让我以一种通用的方式操作数组的东西。是的,我知道。但是,即使你可以像数组一样,你怎么能提取它的值呢?迟早,您必须进行类型转换并将其转换为最终的混凝土类型。此外,对于{switch{…}}循环中的每个for元素,都必须这样做,因为数组可能类似于[Int8,Int32,Int16,Int16,…]。我认为这不是一个好主意。我想要避免的是在声明中显式,因为实际类型将在运行时根据我从NSData@Eduardo这应该可以很好地工作,我的注意是,只有在您没有通过查看案例中的NSData来定义函数本身的类型的情况下。我基本上把它放在那里,以防你把我的答案抄到操场上
爱德华多:事实上,我收回这句话。如果Swift编译器不知道函数在编译时将返回什么,那么这将不起作用。