首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >T,Optional<T>与vs.,Optional<Void>

T,Optional<T>与vs.,Optional<Void>
EN

Stack Overflow用户
提问于 2016-01-20 15:28:33
回答 2查看 273关注 0票数 1
代码语言:javascript
复制
// 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()

有什么关系?为什么Swift编译器总是很高兴,如果类型不是'Void‘?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-20 15:39:17

警告中的关键词是“推断”。斯威夫特不喜欢推断Void,因为这通常不是你的意思。但是,如果您明确地要求它(: Void),那么这很好,如果这是您的意思,您将如何平息警告。

重要的是要识别哪些类型是推断的,哪些类型是显式的。推断是指“从证据和推理而不是从明确的陈述中推断或得出(信息)”。它不是“猜测”或“选择”的同义词。如果类型不明确,则编译器将生成错误。类型必须始终是定义良好的.问题是它是显式定义的,还是通过基于显式信息的推理来定义的。

此语句具有类型推断:

代码语言:javascript
复制
let x = Foo()

Foo()的类型是显式已知的,但是x的类型是根据整个表达式(Foo)的类型推断的。它是明确的,完全明确的,但它是推断的。

此语句没有类型推断:

代码语言:javascript
复制
let x: Foo = Foo()

但是,这里没有任何类型的推论:

代码语言:javascript
复制
var x: Foo? = nil
x = Foo()

第二行中的x (Foo?)类型是显式的,因为它是在上面的行中显式定义的。

这就是为什么您的一些示例会生成警告(当存在Void推断时),而其他示例则不会生成警告(当只有显式使用Void时)。为什么我们关心推断的Void?因为它很容易发生,而且几乎没有用。例如:

代码语言:javascript
复制
func foo() {}
let x = foo()

这是合法的Swift,但它会生成一个“推断为具有类型'()'”的警告。这是一个很容易犯的错误。您希望得到一个警告,至少如果您试图分配一些不返回结果的结果。

那么,我们怎么可能分配不返回结果的结果呢?这是因为每个函数都返回一个结果。如果返回的是Void,我们就可以省略该信息。重要的是要记住,Void并不意味着“无类型”或“无”。它只是()的一个类型别名,它是一个零元素的元组。它和Int一样有效。

上述代码的完整形式如下:

代码语言:javascript
复制
func foo() -> () { return () }
let x = foo()

这将返回相同的警告,因为这是相同的事情。我们可以删除-> ()return (),但它们是存在的,因此如果我们愿意,可以将()分配给x。但我们不太可能想这么做。我们几乎肯定犯了一个错误,编译器警告我们这一点。如果出于某种原因我们想要这种行为,那没问题。合法的斯威夫特。我们只需明确地说明类型,而不是依赖类型推断,那么警告就会消失:

代码语言:javascript
复制
let x: Void = foo()

Swift在你的例子中生成警告是非常一致的,你真的想要那些警告。一点也不武断。

编辑:您添加了不同的示例:

代码语言:javascript
复制
var v = Optional<Void>()

这将生成错误:ambiguous use of 'init()'。这是因为编译器不确定您指的是Optional.init(),它是.None,还是Optional.init(_ some: ()),它是.Some(())。不明确的类型是被禁止的,所以你会得到一个严重的错误。

在Swift中,任何值都将与其等效的1元组隐式转换。例如,1(1)是不同的类型。第一个是Int,第二个是包含Int的元组。但是Swift会为您默默地在这两者之间进行转换(这就是为什么您有时会在错误消息中的令人惊讶的地方看到括号)。所以foo()foo(())是同一回事。在几乎所有可能的情况下,这都无关紧要。但是在这种情况下,类型实际上是(),这很重要,并且使事情变得模糊不清。

代码语言:javascript
复制
var i = Optional<Int>()

这明确地引用了Optional.init()并返回了nil

票数 2
EN

Stack Overflow用户

发布于 2016-01-20 15:40:53

编译器警告您使用“虚拟”类型Void,它实际上是一个空元组()的别名,它没有太多的用法。

如果您没有明确指定您希望变量类型为Void,并让编译器推断类型,它将警告您这一点,因为您可能一开始就不想这样做。

例如:

代码语言:javascript
复制
func doSomething() -> Void {
}

let a = doSomething()

将给您一个警告,因为无论如何,只有一个可能的值doSomething()可以返回-一个空元组。

另一方面,

代码语言:javascript
复制
let a: Void = doSomething()

当您显式地告诉编译器您需要一个Void变量时,不会生成警告。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34904046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档