苹果 Swift:类型转换泛型

6

我正在编写一些 Swift 代码,其中包含一个泛型类型的数组:

let _data: Array<T> = T[]()

在我的代码中,稍后需要确定数组中存储的类型。我尝试使用文档中描述的类型转换技术(尽管它不适用于泛型)。

switch self._data {
case let doubleData as Array<Double>:
  // Do something with doubleData
case let floatData as Array<Float>:
  // Do something with floatData
default:
  return nil // If the data type is unknown return nil
}

上述的switch语句在编译时会导致以下错误:
  1. 在代码路径/code.viperscience/Adder/src/Adder Library/Matrix.swift:45:3处,生成IR SIL函数@_TFC19Adder_Example___Mac6Matrix9transposeUS_7Element__fGS0_Q__FT_GSqGS0_Q___时出错:0:错误:无法执行命令:分段错误:11 0:错误:由于信号而导致swift前端命令失败(使用-v查看调用)命令/Applications/Xcode6-Beta2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift以退出码254失败
有人知道如何将我的通用数据转换为其实际类型以便采取特定操作吗?

尝试使用 as?,但我认为在你的情况下这是编译器的错误...请报告它! - Jack
1
我尝试了可选项,但它没有起作用。我同意这可能是编译器的错误。这不是我看到的第一个与泛型相关的错误... - nalyd88
2个回答

2
在Swift中,as运算符类似于C++中的dynamic_cast,可用于将对象进行向下转型

假设您有一个类型为A的对象a,只有在类型B与类型A相同或BA的子类时,才能编写let a as B
在您的情况下,显然Array<T>并不总是可以向下转型为Array<Double>Array<Float>,因此编译器会报告错误。
一个简单的解决方法是先转换为AnyObject,然后向下转型为Array<Double>Array<Float>
let anyData: AnyObject = self._data;
switch anyData {
case let doubleData as? Array<Double>: // use as? operator, instead of as,
                                       // to avoid runtime exception
  // Do something with doubleData
case let floatData as? Array<Float>:
  // Do something with floatData
default:
  return nil // If the data type is unknown return nil

感谢您的帮助,但是我尝试了您的解决方案却毫无效果。尽管您的解释很有帮助,我意识到Array<T>并不总是可以向下转型为Array<Float>或Array<Double>,但这不是switch语句要做的吗?这真的不应该成为问题...我想这可能是编译器的错误。另外,使用As?运算符只会生成另一个错误。苹果文档(请参见我的链接)并不使用As?运算符,而是仅使用As运算符。 - nalyd88

1
假设你有一个按钮数组:
let views: [NSView] = [NSButton(), NSButton(), NSButton()]

你可以使用这些转换:

let viewsAreButtons = views is [NSButton]  // returns true
let buttonsForSure = views as! [NSButton]  // crashes if you are wrong
let buttonsMaybe = views as? [NSButton]    // optionally set

如果您尝试像下面这样在开关语句中使用“as”,它将无法正常工作。编译器(Swift 1.2 Xcode 6.3b1)会显示:“无法使用类型为[NSButton]的向下转型模式。”

switch views {
  case let buttons as [NSButton]:
    println("Buttons")
  default:
    println("something else")
}

称之为限制。向您的使用案例提交一个雷达。Swift团队似乎真的在倾听反馈。如果您真的想让它工作,可以定义自己的模式匹配运算符。在这种情况下,它将是这样的:
struct ButtonArray { }
let isButtonArray = ButtonArray()

func ~=(pattern: ButtonArray, value: [NSView]) -> Bool {
    return value is [NSButton]
}

那么这个有效:
switch views {
  case isButtonArray:
      println("Buttons")    // This gets printed.
  default:
     println("something else")
}

在 Playground 中尝试它。希望它有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接