为什么我们需要将可选选项显式转换为Any?

时间:2018-12-16 19:33:52

标签: swift casting optional

根据Apple Doc

  

Any类型表示任何类型的值,包括可选类型。   如果您使用可选值(其中一个值   类型为Any。如果确实需要使用可选的   值作为Any值,可以使用as运算符来显式转换   可选为Any,如下所示。

var things = [Any]()
things.append(3)                     // No warning
let optionalNumber: Int? = 3
things.append(optionalNumber)        // Warning, even though Any also represents optional types.
things.append(optionalNumber as Any) // No warning

我们为什么需要将可选内容显式转换为Any

1 个答案:

答案 0 :(得分:4)

每种类型都可以隐式提升为该类型的可选。这意味着当您将T?投射到Any时,很难知道它是最初的T还是最初的T?(甚至是T??或更糟) 。最令人困惑的是,Any可以提升为Any?,并且Any?的类型为Any,因此要说出AnyAny?之间的区别,Any??Any???(等等)非常棘手,有时甚至是不可能的。

Any在Swift中是一个非常棘手的类型,几乎不应该使用。除了显式欺骗编译器(在某些非常花哨和脆弱的类型擦除器中)之外,我不知道在任何情况下将Any作为变量类型是有意义的,并且绝对不是[Any]。如果您创建的是[Any],那么您走的是一条不好的路,

在极少数情况下,将Any作为函数参数类型是有意义的(print()最著名),但是在应用程序级代码中极为罕见。如果您发现自己需要Any,则可能是做错了什么,编译器会对此大惊小怪,并经常使您编写额外的as代码以确保您的意思确实很杂乱你在说什么。

仅给出具体的解释,当您输入Any时,可选性往往会丢失。因此,请考虑这种情况:

let number: Int = 3
let optionalNumber: Int? = 3
let nilNumber: Int? = nil

let anyNumber = number as Any
let anyOptional = optionalNumber as Any
let anyNil = nilNumber as Any

if anyNumber is Int { print("number is Int")} // yes
if anyOptional is Int { print("optional number is Int")} // yes
if anyNil is Int { print("nil is Int")} // no

if anyNil is Int? { print("nil is Int?")}
// -> Error: Cannot downcast from 'Any' to a more optional type 'Int?'

老鼠。

我们无法以与放入可选方式相同的方式获得可选配件。我们当然可以对其进行推广:

if (anyNil as Any?) is Int? { print("nil is Int?") }  // yes

但是我们可以采用任何方式进行推广,因为所有内容本身都是可选的:

if (anyNumber as Any?) is Int? { print("number is Int?")}  // also yes

所以,嗯。老鼠我们真的不知道它最初是否是可选的。情况一团糟,编译器警告您,如果您走的很远,那将会是一团糟。 T-> Any有点魔术。 T-> T?也是一点魔术。结合这两种魔术,您最好确切地知道自己在做什么。