新的SwiftUI教程具有以下代码:
struct ContentView: View {
var body: some View {
Text("Hello World")
}
}
第二行单词some
和在其网站上被高亮显示,就像它是一个关键字一样。
Swift
5.1似乎没有some
作为关键字,而且我也看不出该词some
还有什么其他用处,因为它通常位于类型所在的位置。是否有Swift的未发布新版本?以某种我不知道的方式在类型上使用的函数吗?
关键字有some
什么作用?
some View
是SE-0244引入的不透明结果类型,在带有Xcode 11的Swift
5.1中可用。您可以将其视为“反向”通用占位符。
与调用方可以满足的常规通用占位符不同:
protocol P {}
struct S1 : P {}
struct S2 : P {}
func foo<T : P>(_ x: T) {}
foo(S1()) // Caller chooses T == S1.
foo(S2()) // Caller chooses T == S2.
不透明的结果类型是 实现 满足的隐式通用占位符,因此您可以考虑一下:
func bar() -> some P {
return S1() // Implementation chooses S1 for the opaque result.
}
看起来像这样:
func bar() -> <Output : P> Output {
return S1() // Implementation chooses Output == S1.
}
实际上,此功能的最终目标是允许以更明确的形式使用反向泛型,这也将使您添加约束,例如-> <T : Collection> T where T.Element == Int
。有关更多信息,请参见此帖子。
要摆脱的主要问题是,函数返回some P
是一个函数,该函数返回符合的特定 单个 具体类型的值P
。尝试在函数中返回不同的符合类型会产生编译器错误:
// error: Function declares an opaque return type, but the return
// statements in its body do not have matching underlying types.
func bar(_ x: Int) -> some P {
if x > 10 {
return S1()
} else {
return S2()
}
}
因为隐式通用占位符不能由多种类型满足。
这与returning函数相反P
,后者可以用于表示 两者 S1
和S2
因为它表示任意P
符合的值:
func baz(_ x: Int) -> P {
if x > 10 {
return S1()
} else {
return S2()
}
}
好的,不透明结果类型-> some P
比协议返回类型有什么好处-> P
?
当前协议的主要限制是PAT(具有关联类型的协议)不能用作实际类型。尽管此限制在将来的语言版本中可能会取消,但由于不透明的结果类型实际上只是通用的占位符,因此今天它们可以与PATs一起使用。
这意味着您可以执行以下操作:
func giveMeACollection() -> some Collection {
return [1, 2, 3]
}
let collection = giveMeACollection()
print(collection.count) // 3
由于不透明的结果类型强制返回单个具体类型,因此编译器知道对同一函数的两次调用必须返回相同类型的两个值。
这意味着您可以执行以下操作:
// foo() -> <Output : Equatable> Output {
func foo() -> some Equatable {
return 5 // The opaque result type is inferred to be Int.
}
let x = foo()
let y = foo()
print(x == y) // Legal both x and y have the return type of foo.
这是合法的,因为编译器知道两者x
并且y
具有相同的具体类型。这是==
两个参数类型都为的重要要求Self
。
protocol Equatable {
static func == (lhs: Self, rhs: Self) -> Bool
}
这意味着它期望两个值都与具体符合类型相同。即使Equatable
可以用作类型,也无法将两个任意Equatable
符合的值相互比较,例如:
func foo(_ x: Int) -> Equatable { // Assume this is legal.
if x > 10 {
return 0
} else {
return "hello world"
}
}
let x = foo(20)
let y = foo(5)
print(x == y) // Illegal.
由于编译器无法证明两个任意Equatable
值具有相同的基础具体类型。
In a similar manner, if we introduced another opaque type returning function:
// foo() -> <Output1 : Equatable> Output1 {
func foo() -> some Equatable {
return 5 // The opaque result type is inferred to be Int.
}
// bar() -> <Output2 : Equatable> Output2 {
func bar() -> some Equatable {
return "" // The opaque result type is inferred to be String.
}
let x = foo()
let y = bar()
print(x == y) // Illegal, the return type of foo != return type of bar.
The example becomes illegal because although both foo
and bar
return some Equatable
, their “reverse” generic placeholders Output1
and Output2
could
be satisfied by different types.
Unlike regular protocol-typed values, opaque result types compose well with
regular generic placeholders, for example:
protocol P {
var i: Int { get }
}
struct S : P {
var i: Int
}
func makeP() -> some P { // Opaque result type inferred to be S.
return S(i: .random(in: 0 ..< 10))
}
func bar<T : P>(_ x: T, _ y: T) -> T {
return x.i < y.i ? x : y
}
let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Legal, T is inferred to be the return type of makeP.
This wouldn’t have worked if makeP
had just returned P
, as two P
values
may have different underlying concrete types, for example:
struct T : P {
var i: Int
}
func makeP() -> P {
if .random() { // 50:50 chance of picking each branch.
return S(i: 0)
} else {
return T(i: 1)
}
}
let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Illegal.
At this point you may be thinking to yourself, why not just write the code as:
func makeP() -> S {
return S(i: 0)
}
Well, the use of an opaque result type allows you to make the type S
an
implementation detail by exposing only the interface provided by P
, giving
you flexibility of changing the concrete type later down the line without
breaking any code that depends on the function.
For example, you could replace:
func makeP() -> some P {
return S(i: 0)
}
with:
func makeP() -> some P {
return T(i: 1)
}
without breaking any code that calls makeP()
.
See the Opaque Types section of the language guide and the Swift
evolution proposal for further
information on this feature.
问题内容: 来自标准库的文件包含围绕228行的以下几行代码: 在这种情况下是什么意思,或者通常是什么关键字? 问题答案: 是Swift 3中的新访问级别,随实现而引入 SE-0117允许区分公共访问权限和公共替代权限 从2016年8月7日开始,Swift 3快照和Xcode 8 beta 6都可以使用它。 简而言之: 在定义模块之外, 可以访问 和 可继承 一个类。一类成员是 可访问 和 可重写
当我用类型定义SwiftUI视图时,我得到了崩溃。当我使用确切的类型时,崩溃消失了。 这会崩溃: 这个工作原理: 有什么想法吗?提前感谢。
问题内容: 请看以下示例: 我已将的功能标记为。这到底是什么意思?我在子类中完全省略了它,并且编译器完全没有抱怨。那么,它是如何要求的呢? 问题答案: 请参见“自动初始化继承”: 规则1 如果子类没有定义任何指定的初始化器,它将自动继承其所有超类指定的初始化器。 规则2 如果您的子类提供了其所有超类指定初始化器的实现(通过按规则1继承它们,或通过提供自定义实现作为其定义的一部分),则它会自动继承所
新的SwiftUI教程包含以下代码: 第二行是单词,在他们的网站上突出显示,就好像它是一个关键字一样。 Swift 5.1似乎没有将作为关键字,我看不出单词还能在那里做什么,因为它去了类型通常去的地方。斯威夫特有没有新的、未宣布的版本?这是一个函数,正在使用的类型,以我不知道的方式? 关键字的作用是什么?
问题内容: 在JavaScript中的关键字可能会相当混乱首次遇到它的时候,人们往往会认为JavaScript是不是面向对象的编程语言。 它是什么? 它解决什么问题? 什么时候合适,什么时候不合适? 问题答案: 它做五件事: 它创建一个新对象。这个对象的类型就是 object 。 它将这个新对象的内部不可访问的 [[prototype]] (即 proto )属性设置为构造函数的外部可访问 原型
Swift 2 引入了 关键字,该关键字可用于确保各种数据已配置就绪。我在这个网站上看到的一个例子演示了一个提交已开发的功能: 我想知道使用< code>guard与使用< code>if条件的老式方法有什么不同。它能给你带来用简单的支票无法得到的好处吗?