【问题标题】:generic protocol that has a variable of type generic protocol具有泛型协议类型变量的泛型协议
【发布时间】:2017-07-15 10:47:59
【问题描述】:

我如何创建一个具有另一个通用协议类型的通用协议?

在我的示例中,我有一个 Heap,它是一个泛型类型的协议,因为我的堆中可以有任何符合 Comparable 协议的元素。

所以在我的priorityQueue中,我也想将它作为一个协议(为了避免代码重复和练习)我希望我的priorityQueue包含一个Heap.T等于PriorityQueue.Item的堆,但我不不知道该怎么做。有什么想法吗?

当然我可以用“抽象类”来做,但这不是重点。

顺便说一句,下面的代码甚至无法编译

代码:

public protocol PriorityQueuable: Hashable {
    associatedtype KeyType: Comparable
    associatedtype ValueType: Comparable

    var key: KeyType { get set }
    var value: ValueType { get set }
}

protocol Heap {
    associatedtype T: Comparable

    var data: [T] { get set }

    mutating func heapify(parentIndex: Int)
}

protocol PriorityQueue {
    associatedtype Item: PriorityQueuable

    //FIXME: doesn't allow me to do that. Why?
    var heap: Heap<Item> { get set }

    // doesn't compile as well 
    // var heap: Heap { get set }   
}

【问题讨论】:

  • 如果将PriorityQueue 设为Heap 的子类会怎样?
  • 由于 Swift 中的数据结构主要是结构体,我想将优先级队列具体实现为结构体。但是由于不允许继承结构,所以我决定不考虑这个选项。 + 这是学习该语言的新机会
  • 尝试用泛型类包装Heap
  • @paper1111 还有其他方法吗?
  • @denis631 你的意思是包装Heap还是什么?

标签: swift generics interface protocols


【解决方案1】:

此代码有效:

public protocol PriorityQueuable: Hashable {
    associatedtype KeyType: Comparable
    associatedtype ValueType: Comparable

    var key: KeyType { get set }
    var value: ValueType { get set }
}

protocol Heap {
    associatedtype T: Comparable

    var data: [T] { get set }

    mutating func heapify(parentIndex: Int)
}

class AnyHeap<U: Comparable>: Heap {
    public init(data: [U], heapify: @escaping (_ parentIndex: Int) -> ()) {
        self.data = data
        self.anyHeapify = heapify
    }

    var anyHeapify: (_ parentIndex: Int) -> ()
    var data: [U]
    func heapify(parentIndex: Int) {
        self.anyHeapify(parentIndex)
    }
}

protocol PriorityQueue {
    associatedtype Item: PriorityQueuable, Comparable

    var heap: AnyHeap<Item> { get set }   
}

请注意,还有一个符合 Heap 的附加 AnyHeap 类。 AnyHeap Heap 由于多态性。 (注意Item必须符合Comparable才能符合协议Heap)实现这些协议非常容易:

class AQueueable: PriorityQueuable, Comparable {
    var hashValue: Int { return 1 }
    var key: String = "Hi"
    var value: String = "YoMaMa"
    static func < (lhs: AQueueable, rhs: AQueueable) -> Bool {
        // implement code
        return false
    }
    static func == (lhs: AQueueable, rhs: AQueueable) -> Bool {
        // implement code
        return false
    }
}

class AQueue: PriorityQueue {
    var heap: AnyHeap = AnyHeap<AQueueable>(data: [AQueueable](), heapify: { parentIndex in
        // implement code
    })
}

【讨论】:

  • 谢谢,但这正是我试图避免的事情,即创建一个泛型类。我只想使用通用协议来解决它。看来,Swift 目前不允许这样做
  • 因为即使是苹果也有 AnyDictionaries 和 AnyArrays...虽然不是很快速和漂亮...
  • 这里有一篇很棒的文章,介绍了为什么 AnyHashable 有效,这样您就可以轻松地创建自己的盒装擦除类型并避免大量泛型:kandelvijaya.com/2016/10/10/…
猜你喜欢
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
相关资源
最近更新 更多