4

我写了一个扩展Int如下。

extension Int {
    func squared () -> Int {
        return self * self
    }
}

print(10.squared()) // works

上面的代码有效。现在我想扩展IntegerType协议,以便 Int、UInt、Int64 等都符合。我的代码如下。

extension IntegerType {

    func squared () -> IntegerType { // this line creates error

        return self * self

    }
}

我得到错误:

Protocol 'IntegerType' 只能用作通用约束,因为它具有 Self 或关联的类型要求

我已经看过这个问题及其视频和这个问题,仍然无法理解。我只知道有一些associatedType在这种情况下是Self但无法连接点。我觉得我对这个Generics主题缺乏知识也是一个原因......

有人可以详细说明一下这个主题,为什么扩展会产生错误?

4

2 回答 2

7

你只需要返回Self

编辑/更新:

注意:您可以在 Swift 4 中扩展所有数值类型(整数和浮点数)来扩展数值协议

斯威夫特 4

extension Numeric {
    func squared() -> Self {
        return self * self
    }
}

斯威夫特 3

extension Integer {
    func squared() -> Self { 
        return self * self
    }
}
于 2016-09-05T23:44:45.760 回答
3

函数返回类型只能是具体的Type

重点是类型。任何自己完全定义的结构、类或协议都是纯类型。 但是,当一个协议或结构依赖于另一个通用类型占位符(例如 T)时,这是一个部分类型。

类型是编译器必须分配特定内存的数据结构。

所以是这样的:

let a = Array<T>()或者let b = T对于编译器在编译时推断的信息不足。

因此,这行不通。

  extension IntegerType {

    func squared () -> IntegerType { // this line creates error

        return self * self

    }
}

这里, IntegerType 是一个部分类型。它是一个通用协议,只有在符合时我们才能知道确切的类型。类似于数组。数组本身不是一种类型。它是一个通用容器。只有当有人使用 Array() 或 Array()... 创建它时,它才有类型。

你也发生了同样的事情。

public protocol IntegerType : _IntegerType, RandomAccessIndexType {

再一次,

public protocol RandomAccessIndexType : BidirectionalIndexType, Strideable, _RandomAccessAmbiguity {
@warn_unused_result
    public func advancedBy(n: Self.Distance) -> Self

再一次,

   public protocol _RandomAccessAmbiguity {
    associatedtype Distance : _SignedIntegerType = Int
   }

因此,由于 RandomAccessIndexType 具有 Self 要求的含义,除非有人符合它,否则 Self 是未知占位符。它是部分类型。

由于 IntegerType 符合 RandomAccessIndexType 和 _RandomAccessAmbuiguity ,这也需要与距离相关的类型。

因此你也不能这样做

let a: IntegerType = 12

同样,IntegerType 需要知道 Self 和 Distance(关联类型)。

然而,Int 提供了这样的细节

public struct Int : SignedIntegerType, Comparable, Equatable {
    /// A type that can represent the number of steps between pairs of
    /// values.
    public typealias Distance = Int

因此你可以这样做

let a:Int = 10

因为它为 SignedIntegerType 提供 Self 并为其其他对应物提供 Distance。

简单地说:

不能在具体类型可以使用的地方使用部分类型。部分类型适用于其他泛型并限制它们。

于 2016-09-06T14:19:29.660 回答