什么是占位符?为什么我们需要为泛型定义占位符数据类型?

时间:2016-10-04 15:48:53

标签: swift generics

func inspect <SomeType> (value: SomeType) {
    print ("Received \(type(of: value)) with the value of \(value)")
}

我正在关注Pro Swift书中的教程,但我无法理解为什么我们需要<SomeType>。这似乎没必要。我们给编译器添加了哪些信息?

作者自己说:

  

注意使用SomeType:直接在尖括号中有一个   函数名称,以及描述value参数的名称。首先   尖括号中的一个是最重要的,因为它定义了   你的占位符数据类型:inspect()表示“有一个   名为inspect()的函数,可以与任何类型的数据类型一起使用,   但无论使用什么数据类型,我都想将其称为   SomeType。“所以,参数值:SomeType现在应该更多   sense:SomeType将被替换为用于的任何数据类型   调用函数。

我不理解占位符数据类型意味着什么?

修改
或者用更好的例子

  func inspect <T> (value1: T, value2: T) {
        // ....
    }

我的问题:我知道T会强制执行value1&amp; value2具有相同的类型,因此<T>的用例是什么。

3 个答案:

答案 0 :(得分:4)

  

我们为编译器提供了哪些附加信息

我们说:&#34;亲爱的编译器:我现在不打算告诉你value的类型是什么,这在宣布一个函数时似乎是不寻常的事情。但是相信我,编译器,你会知道当你看到这个函数如何被调用时它是什么类型的,在这个程序的其他地方。&#34;

答案 1 :(得分:3)

这可能令人困惑,因为该功能不是泛型的一个很好的例子。该函数可以重写为非泛型函数,但仍然完全相同:

func inspect (value: Any) {
    print ("Received \(type(of: value)) with the value of \(value)")
}

在其他情况下,它们变得更有用。例如,如果它像

那样
func inspect <T> (value1: T, value2: T) {
    // ....
}

告诉编译器T可以是任何类型,但两个参数必须是相同类型。如果您在此处使用过Any,则参数可以是任何类型,并且可以是不同类型。

或者

func inspect <T> (value:T) -> T {
    // ....
}

这表示该函数接受任何类型的参数并返回相同类型的。同样,如果您在此使用Any,则声明不要求返回类型与参数类型匹配。

答案 2 :(得分:3)

赞同所提供的答案。

我们只是说你编写了如下代码(没有 <p-pickList [source]="data['brandList']" [target]="data['modelList']" [responsive]="true" dragdrop="true"> <ng-template let-brandList pTemplate="item"> <div style="position: relative;height: 29px;top: 7px;"> <table style="margin: 5px;text-align: center;position: relative;bottom: 14px;font-size: 13px;right: 4px;"> <tr style="border-bottom: 1px solid #d3d5d8"> <td style="border-right: 1px solid #d3d5d8"> <span>{{brandList.productClass}}</span> </td> <td style="border-right: 1px solid #d3d5d8"> <span title="{{brandList.model}}" style="display: inline-block;width: 69px;white-space: nowrap;overflow: hidden !important;text-overflow: ellipsis;top: 3px;position: relative;">{{brandList.model}}</span> </td> <td style="border-right: 1px solid #d3d5d8"> <span>{{(brandList.brand).trim()}}</span> </td> </tr> </table> </div> </ng-template> </p-pickList> ),看看会发生什么:

<T>

这里func inspect (value1: T, value2: T) { // some operation with value1, value2 } 的类型是什么? T类是结构还是枚举?或者它是你想要的通用类型? 编译器不知道。它会给出以下错误:

  

错误:使用未声明的类型&#39; T&#39;

仅仅因为你用T写了一些东西,它不会神奇地变成一个通用的东西。

为了更好地说明问题,请参阅此代码段:

T

func inspect (value1: T, value2: T) { // some operation with value1, value2 var x = T() var m = U() } class T { var name = "someName" } class U { var name = "someName" } &lt; - 您希望这是类var x = T()的实例还是泛型?

如果没有T<T> 预期将成为x类型的实例。如果您还没有将T定义为某种类型,如果没有,那么您只会收到错误消息。

这就是您使用T看到的实际代码中的原因。实际类型将进入&#39;类型<T>是&#39;持有&#39;以前。 :

T

实际上执行func inspect <T> (value1: T, value2: T) { // some operation with value1, value2 var x = T() // error! var m = U() // No error } class T { var name = "someName" } class U { var name = "someName" } 会产生错误:

  

&#39; T&#39;无法构造,因为它没有可访问的初始值设定项

如果编译器没有发现这个错误,那么函数内部的x = T()将是非泛型的,并且会来自类定义或只是未知......

我们T的原因是创建一个本地香草类型,避免来自外部的错误期望。 (虽然如果你限制它,那么它会有所不同)

为什么Swift取代泛型 <T> class T?我假设它是因为Swift优先考虑本地范围。