Swift 关联类型受限于集合的协议扩展,不能使用下标
Swift Protocol Extension with AssociatedType Constrained to Collection, Can't Use Subscript
我正在尝试编写一个符合集合协议的协议,它有一个 associatedType - Object 和一个 属性 对象。
protocol DDCDataSource: Collection
{
associatedtype Object
var object: Object {get set}
}
我想为 Object 也符合 Collection 协议的情况添加一些默认功能,即直接 return Object 实现这些必需的 Collection 属性和函数。除了 Collection 对下标的要求外,这似乎都有效。
Cannot subscript a value of type 'Self.Object' with an index of type 'Self.Object.Index'
extension DDCDataSource where Object: Collection
{
typealias Index = Object.Index
var startIndex: Object.Index {
get {
return object.startIndex
}
}
var endIndex: Object.Index {
get {
return object.endIndex
}
}
subscript(position: Object.Index) -> Element
{
return object[position]
}
func index(after i: Object.Index) -> Object.Index {
return object.index(after: i)
}
}
首先,我认为你应该定义Element
,
其次,您使用 object[position]
, Object Conforms To Collection ,但它不是 Collection Types 。显然不是Array。
As apple
says: array
conforms to CustomDebugStringConvertible / CustomReflectable /
CustomStringConvertible / CVarArg /Decodable / Encodable /
ExpressibleByArrayLiteral /MutableCollection /RandomAccessCollection /
RangeReplaceableCollection
我觉得extension DDCDataSource where Object: Array
比较好
数组中的元素应Element
定义。只是提示。
试试这个:
subscript(position:Object.Index) -> Element
{
var element: Element
guard let elementObject = object[position] else {
//handle the case of 'object' being 'nil' and exit the current scope
}
element = elementObject as! Element
}
简答:更改下标方法的return类型
至 Object.Element
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
或添加类型别名(与为 Index
类型所做的方式类似)
typealias Element = Object.Element
subscript(position: Object.Index) -> Element {
return object[position]
}
这使得代码编译并 运行 符合预期。
解释:Collection
的subscript
method声明为
subscript(position: Self.Index) -> Self.Element { get }
其中 Self.Index
和 Self.Element
是关联类型
的`集合。使用您的代码
subscript(position: Object.Index) -> Element {
return object[position]
}
编译器将 Self.Index
推断为 Object.Index
,但是有
Self.Element
和 Object.Element
之间没有关系(这是
return 由 object[position]
编辑)。错误变得更加明显
如果你添加一个显式转换:
subscript(position: Object.Index) -> Element {
return object[position] as Element
}
现在编译器报错了
error: 'Self.Object.Element' is not convertible to 'Self.Element'; did you mean to use 'as!' to force downcast?
正确的解决方案是不是强制转换而是编译器
通过添加类型别名知道 Self.Element
是 Object.Element
或者通过更改 return 类型
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
以便编译器 推断 DDCDataSource.Element
为 Object.Element
.
完整的独立示例:(Swift 4,Xcode 9 beta 6)
(请注意,对于只读计算,您可以省略 get
关键字
属性。)
protocol DDCDataSource: Collection {
associatedtype Object
var object: Object { get set }
}
extension DDCDataSource where Object: Collection {
var startIndex: Object.Index {
return object.startIndex
}
var endIndex: Object.Index {
return object.endIndex
}
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
func index(after i: Object.Index) -> Object.Index {
return object.index(after: i)
}
}
struct MyDataSource: DDCDataSource {
var object = [1, 2, 3]
}
let mds = MyDataSource()
print(mds[1]) // 2
for x in mds { print(x) } // 1 2 3
我正在尝试编写一个符合集合协议的协议,它有一个 associatedType - Object 和一个 属性 对象。
protocol DDCDataSource: Collection
{
associatedtype Object
var object: Object {get set}
}
我想为 Object 也符合 Collection 协议的情况添加一些默认功能,即直接 return Object 实现这些必需的 Collection 属性和函数。除了 Collection 对下标的要求外,这似乎都有效。
Cannot subscript a value of type 'Self.Object' with an index of type 'Self.Object.Index'
extension DDCDataSource where Object: Collection
{
typealias Index = Object.Index
var startIndex: Object.Index {
get {
return object.startIndex
}
}
var endIndex: Object.Index {
get {
return object.endIndex
}
}
subscript(position: Object.Index) -> Element
{
return object[position]
}
func index(after i: Object.Index) -> Object.Index {
return object.index(after: i)
}
}
首先,我认为你应该定义Element
,
其次,您使用 object[position]
, Object Conforms To Collection ,但它不是 Collection Types 。显然不是Array。
As apple says: array conforms to CustomDebugStringConvertible / CustomReflectable / CustomStringConvertible / CVarArg /Decodable / Encodable / ExpressibleByArrayLiteral /MutableCollection /RandomAccessCollection / RangeReplaceableCollection
我觉得extension DDCDataSource where Object: Array
比较好
数组中的元素应Element
定义。只是提示。
试试这个:
subscript(position:Object.Index) -> Element
{
var element: Element
guard let elementObject = object[position] else {
//handle the case of 'object' being 'nil' and exit the current scope
}
element = elementObject as! Element
}
简答:更改下标方法的return类型
至 Object.Element
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
或添加类型别名(与为 Index
类型所做的方式类似)
typealias Element = Object.Element
subscript(position: Object.Index) -> Element {
return object[position]
}
这使得代码编译并 运行 符合预期。
解释:Collection
的subscript
method声明为
subscript(position: Self.Index) -> Self.Element { get }
其中 Self.Index
和 Self.Element
是关联类型
的`集合。使用您的代码
subscript(position: Object.Index) -> Element {
return object[position]
}
编译器将 Self.Index
推断为 Object.Index
,但是有
Self.Element
和 Object.Element
之间没有关系(这是
return 由 object[position]
编辑)。错误变得更加明显
如果你添加一个显式转换:
subscript(position: Object.Index) -> Element {
return object[position] as Element
}
现在编译器报错了
error: 'Self.Object.Element' is not convertible to 'Self.Element'; did you mean to use 'as!' to force downcast?
正确的解决方案是不是强制转换而是编译器
通过添加类型别名知道 Self.Element
是 Object.Element
或者通过更改 return 类型
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
以便编译器 推断 DDCDataSource.Element
为 Object.Element
.
完整的独立示例:(Swift 4,Xcode 9 beta 6)
(请注意,对于只读计算,您可以省略 get
关键字
属性。)
protocol DDCDataSource: Collection {
associatedtype Object
var object: Object { get set }
}
extension DDCDataSource where Object: Collection {
var startIndex: Object.Index {
return object.startIndex
}
var endIndex: Object.Index {
return object.endIndex
}
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
func index(after i: Object.Index) -> Object.Index {
return object.index(after: i)
}
}
struct MyDataSource: DDCDataSource {
var object = [1, 2, 3]
}
let mds = MyDataSource()
print(mds[1]) // 2
for x in mds { print(x) } // 1 2 3