我有一个基于Comparable的通用二进制搜索树:
public class BSTree<T: Comparable> {
...
public func insert(_ val: T, _ n: Int) {
...
}
@discardableResult
public func delete(_ val: T, _ n: Int) -> Int {
...
}
...
}
如果T是算术类型,我想增加提供值之和的能力。我尝试了以下方法:
public class BSTree<T: Comparable> {
private var sumStorage: T?
...
public func insert(_ val: T, _ n: Int) {
if let arithVal = val as? AdditiveArithmetic {
for _ in 0 ..< n { sumStorage += arithVal }
}
...
}
@discardableResult
public func delete(_ val: T, _ n: Int) -> Int {
...
numDeleted = ...
if let arithVal = val as? AdditiveArithmetic {
for _ in 0 ..< numDeleted { sumStorage -= arithVal }
}
}
...
}
extension BSTree where T: AdditiveArithmetic {
public var sum: T {
sumStorage as? T ?? T.zero
}
}
[当然,当我尝试将val
强制转换为AdditiveArithmetic
时,我得到“协议'AdditiveArithmetic'只能用作通用约束,因为它具有Self或关联的类型要求”。加号sumStorage
不是AdditiveArithmetic
,因此我无法添加它,也无法将其作为扩展名的存储属性,因为...您只是不能。
我最终想到的是使用继承:
class SummedBSTree<T>: BSTree<T> where T: AdditiveArithmetic & Comparable {
public var sum = T.zero
override public func insert(_ val: T, _ n: Int) {
super.insert(val, n)
for _ in 0 ..< n { sum += val }
}
@discardableResult
override public func delete(_ val: T, _ n: Int) -> Int {
let numDeleted = super.delete(val, n)
for _ in 0 ..< numDeleted { sum -= val }
return numDeleted
}
}
这是可行的,但似乎是在使用大锤的情况,珠宝商的螺丝刀应该可以完成这项工作。令人沮丧的是,在Swift中,在Objective-C(以及其他类型较少的强类型语言)中如此容易做到的事情如此困难。有人可以提出一种无需子类即可添加求和功能的方法吗?
我希望这会有所帮助。
import UIKit
//https://stackoverflow.com/questions/61784548/swift-extended-capability-for-a-more-restrictive-generic
public class BSTree<T: Comparable> {
var values = [T]()
public func insert(_ val: T, _ n: Int) {
}
@discardableResult
public func delete(_ val: T, _ n: Int) -> Int {
return 42
}
}
extension BSTree where T:AdditiveArithmetic {
var sum: T {
return values.reduce(T.zero, +)
}
}
let g2 = BSTree<Int>()
g2.values = [1,2,3]
g2.sum // 6
let g3 = BSTree<String>()
g3.values = ["1", "2", "3"]
g3.sum // Error