Swift T、 可选<;T>;vs.Void,可选<;无效>; //变量的此声明/定义与预期一样正常 变量i=可选。无 var j:Int? //对于下一行代码,编译器生成一个很好的警告 //推断变量“v1”的类型为“Optional”(也称为“Optional”),这可能是意外的 var v1=可选。无 //但下一句话不会产生任何警告 var v2:无效? //非可选版本产生“相同方式”警告 //变量“v3”推断为具有类型“()”,这可能是意外的 var v3=Void() //但是编译器对下一个代码感觉很好 var v4:Void=Void()
有什么区别?如果类型不是“Void”,为什么Swift编译器总是很高兴?警告中的关键词是“推断”。Swift不喜欢推断Swift T、 可选<;T>;vs.Void,可选<;无效>; //变量的此声明/定义与预期一样正常 变量i=可选。无 var j:Int? //对于下一行代码,编译器生成一个很好的警告 //推断变量“v1”的类型为“Optional”(也称为“Optional”),这可能是意外的 var v1=可选。无 //但下一句话不会产生任何警告 var v2:无效? //非可选版本产生“相同方式”警告 //变量“v3”推断为具有类型“()”,这可能是意外的 var v3=Void() //但是编译器对下一个代码感觉很好 var v4:Void=Void(),swift,Swift,有什么区别?如果类型不是“Void”,为什么Swift编译器总是很高兴?警告中的关键词是“推断”。Swift不喜欢推断Void,因为这通常不是您的意思。但是如果你明确地要求它(:Void),那就没关系了,如果这是你的意思,你将如何消除警告 识别哪些类型是推断的,哪些是显式的,这一点很重要。推断是“从证据和推理而不是从明确的陈述中推断或总结(信息)”。它不是“猜测”或“选择”的同义词。如果类型不明确,编译器将生成错误。类型必须始终定义良好。问题是它是明确定义的,还是通过基于明确信息的推理来定义的
Void
,因为这通常不是您的意思。但是如果你明确地要求它(:Void
),那就没关系了,如果这是你的意思,你将如何消除警告
识别哪些类型是推断的,哪些是显式的,这一点很重要。推断是“从证据和推理而不是从明确的陈述中推断或总结(信息)”。它不是“猜测”或“选择”的同义词。如果类型不明确,编译器将生成错误。类型必须始终定义良好。问题是它是明确定义的,还是通过基于明确信息的推理来定义的
此语句具有类型推断:
// this declaration / definition of variable is OK, as expected
var i = Optional<Int>.None
var j:Int?
// for the next line of code compiler produce a nice warning
// Variable 'v1' inferred to have type 'Optional<Void>' (aka 'Optional<()>'), which may be unexpected
var v1 = Optional<Void>.None
// but the next sentence doesn't produce any warning
var v2:Void?
// nonoptional version produce the warning 'the same way'
// Variable 'v3' inferred to have type '()', which may be unexpected
var v3 = Void()
// but the compiler feels fine with the next
var v4: Void = Void()
let x = Foo()
Foo()
的类型是明确已知的,但是x
的类型是根据整个表达式的类型推断出来的(Foo
)。它的定义很明确,完全没有歧义,但它是推断出来的
此语句没有类型推断:
// this declaration / definition of variable is OK, as expected
var i = Optional<Int>.None
var j:Int?
// for the next line of code compiler produce a nice warning
// Variable 'v1' inferred to have type 'Optional<Void>' (aka 'Optional<()>'), which may be unexpected
var v1 = Optional<Void>.None
// but the next sentence doesn't produce any warning
var v2:Void?
// nonoptional version produce the warning 'the same way'
// Variable 'v3' inferred to have type '()', which may be unexpected
var v3 = Void()
// but the compiler feels fine with the next
var v4: Void = Void()
let x = Foo()
但是,这里也没有类型推断:
let x: Foo = Foo()
第二行中的x
(Foo?
)类型是显式的,因为它是在上一行中显式定义的
这就是为什么您的一些示例会生成警告(当存在Void
推断时),而其他示例不会生成警告(当仅显式使用Void
时)。为什么我们关心推断的无效
?因为它很容易偶然发生,而且几乎没有任何用处。例如:
var x: Foo? = nil
x = Foo()
var i = Optional<Int>()
这是合法的Swift,但它会生成“推断为具有类型“()””警告。这是一个很容易犯的错误。如果您试图分配某个不返回结果的结果,则至少需要一个警告
那么,我们怎么可能分配不返回结果的结果呢?这是因为每个函数都返回一个结果。如果返回值为Void
,我们只允许忽略该信息。重要的是要记住,Void
并不意味着“没有类型”或“什么都没有”。它只是()
的类型别名,它是一个由零元素组成的元组。它与Int
一样有效
上述代码的完整形式为:
func foo() {}
let x = foo()
这会返回相同的警告,因为它是相同的东西。我们可以删除->()
和返回()
,但它们是存在的,因此如果需要,我们可以将()
分配给x
。但我们不太可能想这么做。我们几乎肯定犯了错误,编译器警告我们这一点。如果出于某种原因我们想要这种行为,那没关系。这是合法的。我们只需明确说明类型,而不是依赖类型推断,警告就会消失:
func foo() -> () { return () }
let x = foo()
Swift在您的示例中生成警告时非常一致,您确实需要这些警告。这完全不是武断的
编辑:您添加了不同的示例:
let x: Void = foo()
这明确地引用了
Optional.init()
,并返回nil
编译器警告您“dummy”类型Void
,它实际上是空元组的别名()
,并且没有太多用法
如果您没有明确指定希望变量的类型为Void
,并让编译器推断该类型,它将对此发出警告,因为您可能一开始就不想这样做
例如:
var x: Foo? = nil
x = Foo()
var i = Optional<Int>()
将给您一个警告,因为无论如何只有一个可能的值doSomething()
可以返回-一个空元组
另一方面,
func doSomething() -> Void {
}
let a = doSomething()
当您明确告诉编译器您需要一个
Void
变量时,不会生成警告。v2
仅声明,请尝试为其赋值,并查看编译器是否可以使用that@Cristicv2有默认值nil这是一个查找,我发现了相同的结果。为什么其他类型的人没有警告?顺便说一下,看看func f()throws->Void和一些有价值的用法,比如guard let v=try?f()(将在运行时知道)Rob,拜托,你能比较一下这两句话吗?var v=Optional();var i=Optional()我删除了关于Any
的讨论。我记得对Any
和AnyObject
进行了特殊处理,但我最近的测试表明,它们与其他协议得到了相同的处理。我不确定这是否是Swift更高版本中的变化(我记得在Swift的早期版本中有一个关于AnyObject
的特别警告),但现在看来肯定不是这样。非常感谢你的更新!特别是它的第一段。是的,正如你所写的“Swift不喜欢推断Void,因为它通常不是你的意思”似乎是真的,不幸的是没有任何真正的原因。实际上这不是一个大问题。我的期望是编译器