为什么我会收到错误消息“Protocol … can only be used as a generic constraint because it has Self or associated type requirements”?
Why do I get the error “Protocol … can only be used as a generic constraint because it has Self or associated type requirements”?
我在 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' can only be used as a generic constraint because it has Self or associated type requirements
我已经看到了this question and its video & this题,还是没看懂。我只知道有一些 associatedType
在这种情况下是 Self
但无法连接点。我觉得我对 Generics
主题缺乏了解也是一个原因...
有人可以详细说明一下这个主题吗?为什么扩展会产生错误?
你只需要 return Self
edit/update:
注意:您可以在 Swift 中扩展所有数字类型(整数和浮点数) 4 扩展数字协议
Swift 4
extension Numeric {
func squared() -> Self {
return self * self
}
}
Swift 3
extension Integer {
func squared() -> Self {
return self * self
}
}
函数return类型只能是具体的Type
。
重点是类型。 任何完全在自身定义的结构,class 或协议都是纯类型。 但是当协议或结构依赖于另一个通用类型占位符时,例如 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 具有自我要求的含义,直到并且除非有人符合它,否则自我是未知的占位符。它是部分类型。
因为 IntegerType 符合 RandomAccessIndexType 和 _RandomAccessAmbuiguity,这也需要 Distance 关联类型。
所以你也不能这样做
let a: IntegerType = 12
同样 IntegerType 需要知道 Self 和 Distance (associatedType)。
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。
简单地说:
可以使用具体类型的地方不能使用分部类型。部分类型适用于其他泛型并对其进行约束。
我在 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' can only be used as a generic constraint because it has Self or associated type requirements
我已经看到了this question and its video & this题,还是没看懂。我只知道有一些 associatedType
在这种情况下是 Self
但无法连接点。我觉得我对 Generics
主题缺乏了解也是一个原因...
有人可以详细说明一下这个主题吗?为什么扩展会产生错误?
你只需要 return Self
edit/update:
注意:您可以在 Swift 中扩展所有数字类型(整数和浮点数) 4 扩展数字协议
Swift 4
extension Numeric {
func squared() -> Self {
return self * self
}
}
Swift 3
extension Integer {
func squared() -> Self {
return self * self
}
}
函数return类型只能是具体的Type
。
重点是类型。 任何完全在自身定义的结构,class 或协议都是纯类型。 但是当协议或结构依赖于另一个通用类型占位符时,例如 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 具有自我要求的含义,直到并且除非有人符合它,否则自我是未知的占位符。它是部分类型。
因为 IntegerType 符合 RandomAccessIndexType 和 _RandomAccessAmbuiguity,这也需要 Distance 关联类型。
所以你也不能这样做
let a: IntegerType = 12
同样 IntegerType 需要知道 Self 和 Distance (associatedType)。
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。
简单地说:
可以使用具体类型的地方不能使用分部类型。部分类型适用于其他泛型并对其进行约束。