为什么在泛型中未解析的泛型类型是合法的?

7

也许我太蠢了,我意识到应该知道这种事情,但是我被这个惊到了:

class Wrapper<T> {
    let value: T
    var wrapper: Wrapper? // ok
    init(value: T) {
        self.value = value
    }
}
class Thing {
    var wrapper: Wrapper? // error
}

错误在于在Thing类内部,当我声明类型时,必须解析包装器泛型;例如,我需要这样说:
var wrapper: Wrapper<String>?

为什么在Wrapper内部声明属性的类型为Wrapper是合法的,但在其他地方却不行?是什么原因让Wrapper内部的声明合法?这是因为编译器假定在Wrapper内部,Wrapper意味着Wrapper<T>吗?

2
https://www.swiftbysundell.com/tips/using-self-to-refer-to-enclosing-types/ - user652038
@Jessy 我觉得我知道 extension 的一部分,但这似乎有所不同。 - matt
2
对于大多数情况来说,它已经失去了其有用性。 - user652038
经过多次编辑,我认为我已经将我的答案简化成了一个明智而不过长的东西。如果你在我反复编辑它的时候尝试阅读它,很抱歉。我应该离线写下来。 - Chip Jarred
@ChipJarred 哪里,我也是这样做的:先回答再疯狂编辑。基本上你是在说我的猜测是正确的;它暗示了 T 是相同的 T。有趣的是我以前从未注意到这个快捷方式。 - matt
@matt 是的,基本上就是这样。更有趣的问题是为什么有时候你可以通过它符合的协议来引用一个未知类型,而有时候你却不能。这涉及到SelfassociatedType约束,以及对some的使用。 - Chip Jarred
1个回答

4
Wrapper 的情况下,T 已知,因为它是 Wrapper 定义的一部分,因此在没有特化的情况下使用 Wrapper 会被隐式地认为是 Wrapper<T>
Thing 的情况下,没有定义 T,即使有,也不会与 Wrapper 中的T 相同。把它看作类似于这些函数:
func foo(_ x: Int) {
   // x is known here
}

func bar() {
   // x is unheard of here.
}

func foobar(_ x: Int) {
   // x is known here, but it's not the same x as in foo
}

当然,区别在于即使foo必须显式地引用x,而Wrapper可以在其自身定义中推断出T。事实上,如果Wrapper想要引用另一个专门针对不同类型的Wrapper,它必须明确说明:
class Wrapper<T> {
   ...
   func someConversion<U>(otherWrapper: Wrapper<U>) {
   }
}

在另一方面,Thing是在Wrapper之外声明的,因此它不知道关于T的任何信息。所以从它的角度来看。
var wrapper: Wrapper?

这和毫无意义一样无聊。

var values: Array?

编译器不知道元素类型,就无法创建数组。同样地,如果不知道 T 的内容,编译器也无法创建您的 Wrapper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接