具有约束类型的Swift协议扩展约束到集合,不能使用下标

时间:2017-09-09 08:10:16

标签: swift generics swift-protocols protocol-extension swift3.2

我正在尝试编写符合Collection Protocol的协议,它有一个associatedType - Object和一个属性对象。

protocol DDCDataSource: Collection
{
    associatedtype Object
    var object: Object {get set}
}

我想为Object也符合Collection协议的情况添加一些默认功能,即直接返回Object对这些必需Collection属性和函数的实现。除了Collection对下标的要求外,它似乎都有效。

  

无法使用类型为“Self.Object.Index”的索引下标“Self.Object”类型的值

enter image description here

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)
    }
}

3 个答案:

答案 0 :(得分:5)

简答:更改下标方法的返回类型 到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的{​​{3}}被声明为

subscript(position: Self.Index) -> Self.Element { get }

其中Self.IndexSelf.Element是关联类型 收藏。使用您的代码

subscript(position: Object.Index) -> Element {
    return object[position]
}

编译器推断Self.IndexObject.Index,但在那里 Self.ElementObject.Element之间没有任何关系 由object[position]返回。错误变得更加明显 如果你添加一个显式的演员:

subscript(position: Object.Index) -> Element {
    return object[position] as Element
}

现在编译器抱怨

  

错误:'Self.Object.Element'无法转换为'Self.Element';你的意思是用'as!'迫使低垂?

正确的解决方案是强制转换,而是制作编译器 通过添加类型别名,知道Self.ElementObject.Element 或者通过更改返回类型

subscript(position: Object.Index) -> Object.Element {
    return object[position]
}

以便编译器推断 DDCDataSource.ElementObject.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

答案 1 :(得分:0)

首先,我认为你应该定义Element

其次,您使用object[position],Object Conforms To Collection,但它不是Collection Types。显然它不是Array。

  

作为apple says:数组   符合CustomDebugStringConvertible / CustomReflectable /   CustomStringConvertible / CVarArg / Decodable / Encodable /   ExpressibleByArrayLiteral / MutableCollection / RandomAccessCollection /   RangeReplaceableCollection

我认为extension DDCDataSource where Object: Array更好。

数组中的元素应为Element定义。只是提示。

答案 2 :(得分:0)

试试这个:

onload