我在尝试扩展(Int, Int)
或Any
等非正统“类型”时看到此错误:
非名义类型'任何'不能延长
那么什么使一种类型非名义?非名义类型(如Any
或(Int)
)与常规名义类型(如Int
)之间的区别是什么?
答案 0 :(得分:61)
currently accepted answer不正确;实际答案来自Swift系统类型的深层而深奥的部分。
Swift中的大多数类型都是名义类型 - 他们的名字"名称"作为用户代码的一部分在特定模块中声明的类型。看似原始的类型如Int
和Array
实际上是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;他做得很好。