当前位置: 首页 > 面试题库 >

Swift(UI)中的“ some”关键字是什么?

晋奕
2023-03-14
问题内容

新的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,后者可以用于表示 两者 S1S2因为它表示任意P符合的值:

func baz(_ x: Int) -> P {
  if x > 10 {
    return S1()
  } else {
    return S2()
  }
}

好的,不透明结果类型-> some P比协议返回类型有什么好处-> P

1.不透明的结果类型可以与PAT一起使用

当前协议的主要限制是PAT(具有关联类型的协议)不能用作实际类型。尽管此限制在将来的语言版本中可能会取消,但由于不透明的结果类型实际上只是通用的占位符,因此今天它们可以与PATs一起使用。

这意味着您可以执行以下操作:

func giveMeACollection() -> some Collection {
  return [1, 2, 3]
}

let collection = giveMeACollection()
print(collection.count) // 3

2.不透明的结果类型具有标识

由于不透明的结果类型强制返回单个具体类型,因此编译器知道对同一函数的两次调用必须返回相同类型的两个值。

这意味着您可以执行以下操作:

//   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.

3. Opaque result types compose with generic placeholders

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.

Why use an opaque result type over the concrete type?

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条件的老式方法有什么不同。它能给你带来用简单的支票无法得到的好处吗?