可以抛出和不可抛出的方法中的Swift类型推断

可以抛出和不可抛出的方法中的Swift类型推断,第1张

概述您可能知道, Swift可以根据用途推断类型.例如,只要编译器能够推断类型,您就可以使重载方法仅在返回类型上有所不同并自由使用它们.例如,借助于附加的显式类型变量,它将保存此类方法的返回值. 我发现了一些有趣的时刻.想象一下这堂课: class MyClass { enum MyError: Error { case notImplemented case 您可能知道,Swift可以根据用途推断出类型.例如,只要编译器能够推断类型,您就可以使重载方法仅在返回类型上有所不同并自由使用它们.例如,借助于附加的显式类型变量,它将保存此类方法的返回值.

我发现了一些有趣的时刻.想象一下这堂课:

class MyClass {    enum MyError: Error {        case notImplemented        case someException    }    func fun1() throws -> Any {        throw MyError.notImplemented    }    func fun1() -> Int {        return 1    }    func fun2() throws -> Any {        throw MyError.notImplemented    }    func fun2() throws -> Int {        if false {            throw MyError.someException        } else {            return 2        }    }}

当然,它会像:

let myClass = MyClass()// let resul1 = myClass.fun1() // error: ambiguous use of 'fun1()'let result1: Int = myClass.fun1() // OK

但接下来你可以写下这样的东西:

// print(myClass.fun1()) // error: call can throw but is not marked with 'try'// BUTprint(try? myClass.fun1()) // warning: no calls to throwing functions occur within 'try' Expression

所以看起来像是互相排斥的陈述.编译器试图选择正确的功能;第一次调用它试图强制从Int转换为Any,但是它试图用第二个做什么?

而且,代码就像

if let result2 = try? myClass.fun2() { // No warnings    print(result2)}

将没有警告,所以可以假设编译器能够在这里选择正确的重载(可能基于事实,其中一个重载实际上没有返回任何东西而只抛出).

我最后的假设是对的吗? fun1()的警告是否合乎逻辑?我们是否有一些技巧来欺骗编译器或帮助它进行类型推断?

解决方法 显然你永远不应该写这样的代码.它有太多方法可以咬你,正如你所看到的那样.但是,让我们看看为什么.

首先,尝试只是Swift中的装饰.它不适合编译器.这是给你的.编译器计算出所有类型,然后确定是否需要尝试.它不使用尝试找出类型.你可以在这里看到这个:

class X {    func x() throws -> X {        return self    }}let y = try X().x().x()

您只需要尝试一次,即使链中有多个投掷调用.想象一下,如果你基于throws vs non-throws在x()上创建了重载,这将如何工作.答案是“它没关系”因为编译器不关心try.

接下来是类型推断与类型强制的问题.这是类型推断:

let resul1 = myClass.fun1() // error: ambiguous use of 'fun1()'

斯威夫特永远不会推断出一种模棱两可的类型.这可能是Any或它可能是’`,所以它放弃了.

这不是类型推断(类型已知):

let result1: Int = myClass.fun1() // OK

这也有一个已知的,明确的类型(注意没有?):

let x : Any = try myClass.fun1()

但这需要类型强制(很像你的打印示例)

let x : Any = try? myClass.fun1() // Expression implicitly coerced from `Int?` to `Any`                                  // No calls to throwing function occur within 'try' Expression

为什么这称为Int版本?尝试?返回一个Optional(可以是Any).那么Swift可以选择返回Int的表达式吗?并强迫任何或任何?并强迫任何. Swift几乎总是喜欢Any的真实类型(并且它非常讨厌Any?).这是在代码中避免使用Any的众多原因之一.它以奇怪的方式与Optional交互.有争议的是,这应该是一个错误,但是Any是如此松散的类型,很难确定其所有的角落情况.

那么这如何适用于印刷? print的参数是Any,所以这就像let x:Any = … example而不是像let x = …这样的例子.

在考虑这些事情时要记住一些自动强制:

>每个T都可以轻易地强制到T?
>每个T都可以明确强制为Any
>每个T?也可以明确强迫任何

>任何人都可以被轻易地强迫任何人? (还有任何??,任何???,和任何????等)
>任何? (Any ??,Any ???等)可以明确强制转换为Any

>每个非投掷功能都可以简单地强制转换为投掷版本

>因此,纯粹在“投掷”上超载是危险的

那么混合抛出/非投掷与Any / Any的转换?转换,并尝试投掷?在混合中(将所有东西都推广到可选项中),你创造了一个完美的混乱风暴.

显然你永远不应该写这样的代码.

总结

以上是内存溢出为你收集整理的可以抛出和不可抛出的方法中的Swift类型推断全部内容,希望文章能够帮你解决可以抛出和不可抛出的方法中的Swift类型推断所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1009478.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存