簡體   English   中英

具有約束類型的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協議的情況添加一些默認功能,即直接返回Object對這些必需Collection屬性和函數的實現。 除了Collection對下標的要求外,它似乎都有效。

無法使用類型為“Self.Object.Index”的索引下標“Self.Object”類型的值

在此輸入圖像描述

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

簡答:將下標方法的返回類型更改為Object.Element

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

或添加類型別名(以與您對Index類型類似的方式)

typealias Element = Object.Element

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

這使得代碼按預期編譯和運行。


說明: Collectionsubscript方法聲明為

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

其中Self.IndexSelf.Element是`Collection的關聯類型。 用你的代碼

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.ElementDDCDataSource.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

首先,我認為你應該定義Element

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

正如蘋果所說 :數組符合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

    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM