【发布时间】:2021-12-31 00:35:24
【问题描述】:
我有一个带有 PAT 的协议,它在扩展中提供默认实现。 然后,符合该协议的类提供“覆盖”。 不调用此覆盖,编译器“首选”默认值。
//---- Definition of the protocol with a default implentation, because I am forced to.
protocol Bag: AnyObject {
associatedtype BagObject
func add(_ e: BagObject)
}
extension Bag where BagObject: Equatable {
// I here give a default implementation, because I can't do differently, as this
// is an extension, and it is an extension because it only applies to assoicated
// types that are Equatables
func contains(_ e: BagObject) -> Bool {
print("Default implementation is called")
return false
}
}
///---- Definition of a class that gives a concrete implementation of the protocol
class BagConcreteImplementation<BagObject>: Bag {
var bag = Array<BagObject>()
func add(_ e: BagObject) { bag.append(e) }
}
extension BagConcreteImplementation where BagObject: Equatable {
// I here give a concrete implementation when the generic type is Equatable
func contains(_ e: BagObject) -> Bool {
print("Concrete implementation is called")
return bag.contains(e)
}
}
///---- This is a class that encapsulate a bag, in real life, this class is adding some filtering to objects that can be added to the bag
class AClassThatHaveABag<BagType: Bag> {
typealias BagObject = BagType.BagObject
let myBag: BagType
init(bag: BagType) { myBag = bag }
}
extension AClassThatHaveABag where BagType.BagObject: Equatable {
func contains(_ e: BagObject) {
// The problem here is that the compiler only knows that myBag is a Bag
// of Int and therefore calls the default implementation
// It does not call the concrete implementation of the concrete class that WILL be provided
myBag.contains(e)
}
}
let aBagOfInt = BagConcreteImplementation<Int>()
let objectThatContainsABagOfInt = AClassThatHaveABag(bag: aBagOfInt)
aBagOfInt.contains(0)
objectThatContainsABagOfInt.contains(0)
// Prints
// Concrete implementation is called
// Default implementation is called
我们可以清楚地看到直接调用是调用具体实现,而封装调用是调用默认实现。
如何确保始终调用具体实现,即使是通过封装?
【问题讨论】:
-
你能告诉我们
BagConcreteImplementation.contains函数的调用地址吗 -
@EmilioPelaez 不确定你的问题。在
aBagOfInt.contains(0)调用BagConcreteImplementation.contains并打印Concrete implementation is called。 -
我的错,没注意到滚动条????????♂️