声明一个Swift协议,它具有属性返回值CollectionType <int>?

时间:2016-01-10 07:24:20

标签: swift protocols

类似于

protocol A {
    var intCollection: CollectionType<Int> { get }
}

protocol A {
    typealias T: CollectionType where T.Generator.Element == Int
    var intCollection: T
}

可以在Swift 2.1中使用吗?

Swift 4的更新

Swift 4现在支持此功能! read more in here

2 个答案:

答案 0 :(得分:0)

你不能像在你的问题中那样正确地做这个,并且在这里有关于使用协议作为类型定义的主题的若干线程,其内容本身包含Self或相关类型要求(结果:这是不允许)。参见例如link provided by Christik或帖子Error using associated types and generics

现在,对于上面的示例,您可以执行以下解决方法,但是,可能会模仿您正在寻找的行为

protocol A {
    typealias MyCollectionType
    typealias MyElementType
    func getMyCollection() -> MyCollectionType
    func printMyCollectionType()
    func largestValue() -> MyElementType?
}

struct B<U: Comparable, T: CollectionType where T.Generator.Element == U>: A {
    typealias MyCollectionType = T
    typealias MyElementType = U
    var myCollection : MyCollectionType

    init(coll: MyCollectionType) {
        myCollection = coll
    }

    func getMyCollection() -> MyCollectionType {
        return myCollection
    }

    func printMyCollectionType() {
        print(myCollection.dynamicType)
    }

    func largestValue() -> MyElementType? {
        guard var largestSoFar = myCollection.first else {
            return nil
        }
        for item in myCollection {
            if item > largestSoFar {
                largestSoFar = item
            }
        }
        return largestSoFar
    }
}

因此,您可以在协议A中为通用集合类型实现蓝图,并在&#34;接口类型&#34; B中实现这些蓝图,其中还包含作为成员属性的实际集合。我已采用largestValue()以上/* Examples */ var myArr = B<Int, Array<Int>>(coll: [1, 2, 3]) var mySet = B<Int, Set<Int>>(coll: [10, 20, 30]) var myRange = B<Int, Range<Int>>(coll: 5...10) var myStrArr = B<String, Array<String>>(coll: ["a", "c", "b"]) myArr.printMyCollectionType() // Array<Int> mySet.printMyCollectionType() // Set<Int> myRange.printMyCollectionType() // Range<Int> myStrArr.printMyCollectionType() // Array<String> /* generic T type constrained to protocol 'A' */ func printLargestValue<T: A>(coll: T) { print(coll.largestValue() ?? "Empty collection") } printLargestValue(myArr) // 3 printLargestValue(mySet) // 30 printLargestValue(myRange) // 10 printLargestValue(myStrArr) // c 方法。

使用示例:

{{1}}

答案 1 :(得分:0)

不是嵌套协议,但使用类型擦除器(“任意”结构)相当简单。

protocol A {
    var intCollection: AnyRandomAccessCollection<Int> { get }
}

这实际上对返回值来说通常非常方便,因为调用者通常不太关心实际类型。你只需要在函数结束时抛出一个return AnyRandomAccessCollection(resultArray),这一切都正常。很多stdlib现在返回Any个橡皮擦。对于返回值问题,它几乎总是我推荐的方式。它具有使A具体化的良好副作用,因此使用起来更容易。

如果要保留CollectionType,则需要在创建需要它的函数时限制它。例如:

protocol A {
    typealias IntCollection: CollectionType
    var intCollection: IntCollection { get }
}

extension A where IntCollection.Generator.Element == Int {
    func sum() -> Int {
        return intCollection.reduce(0, combine: +)
    }
}

这并不理想,因为这意味着您可以使用错误类型的集合类型A。他们只是没有sum方法。你也会发现自己在令人惊讶的地方重复“IntCollection.Generator.Element == Int”。

根据我的经验,很少值得这样做,你很快就会回到Arrays(无论如何都是主导的CollectionType)。但是当你需要它时,这是两个主要的方法。这是我们今天最好的。