什么是非名义类型'在斯威夫特?

时间:2014-06-10 01:24:03

标签: swift

我在尝试扩展(Int, Int)Any等非正统“类型”时看到此错误:

  

非名义类型'任何'不能延长

那么什么使一种类型非名义?非名义类型(如Any(Int))与常规名义类型(如Int)之间的区别是什么?

2 个答案:

答案 0 :(得分:61)

currently accepted answer不正确;实际答案来自Swift系统类型的深层而深奥的部分。

Swift中的大多数类型都是名义类型 - 他们的名字"名称"作为用户代码的一部分在特定模块中声明的类型。看似原始的类型如IntArray实际上是Swift模块中定义的结构,它会自动导入到每个Swift源文件中。即使Optional本身是Swift模块中的枚举,尽管编译器添加了一些魔法,如可选链接和强制解包。

少数例外被称为"非名义类型"。可能还有其他人,但主要是:

  • 功能类型,例如(Int) -> String
  • 元组类型,例如(Int, String)
  • 元数据类型,例如String.Type(表达式的类型String.self
  • 存在感,如CustomStringConvertible & Error

存在感需要多一点解释。存在主义包含一个值,其精确类型已被抽象出来,但已知它符合某组协议。例如:

// You can put anything that conforms to `CustomStringConvertible` in `x`
let x: CustomStringConvertible

// You can put anything that conforms to both `CustomStringConvertible` 
// and `Error` in `y`
let y: CustomStringConvertible & Error

// You can put anything in `z`; `Any` is an existential that doesn't
// require you to conform to any particular protocols
let z: Any

非名义类型都只是以某种特殊方式将其他类型组合在一起。 (他们有时被称为"结构类型"因为他们定义了某种通用结构以供其他类型插入。)他们不需要明确定义,他们不需要&#39 ; t属于任何特定模块 - FooKit的(Int, String)与BarKit的(Int, String)相同。但是他们的所有行为都是由语言定义的 - 非名义类型不具备自己的方法或属性,不能符合协议,因此无法扩展。

所以你无法扩展Any,因为Any是一种特殊的东西,它构建在语言中,就像函数类型或元组类型一样。它碰巧有一个用字母写的名字,而不是用标点符号。

(那么为什么你可以扩展CustomStringConvertible?因为,根据上下文,CustomStringConvertible可能意味着协议,或者它可能意味着包含符合值的存在主义协议。当您编写extension CustomStringConvertible时,您正在扩展协议,但是当您编写let x: CustomStringConvertible时,您正在声明一个类型为&#34的变量;存在性包含符合协议的值&#34;。这有点令人困惑,一些Swift的维护者实际上希望要求将存在性写为Any<CustomStringConvertible>以使其更清晰。但是,现在不太可能发生,因为他们正试图保持源稳定性。)

答案 1 :(得分:3)

这有点猜测(编辑:这是错误的,请看Brent's answer),但这里有:

Any是协议,不是实际类型。 “Nominal”一词意味着命名(基于单词的根)。

所以你不能扩展Any,因为它是一个协议,而不是一个实际的类型,你不能扩展(Int, Int),因为那只是一个元组文字,同样不是你可以实际的类型按名称指定。


更新

当然,您可以扩展协议。 Any不是一个协议,它是一种非标称类型(震撼),是另一种。阅读Brent's answer;他做得很好。