Swift-具有更严格限制的泛型扩展功能

问题描述 投票:0回答:1

我有一个基于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(以及其他类型较少的强类型语言)中如此容易做到的事情如此困难。有人可以提出一种无需子类即可添加求和功能的方法吗?

swift generics inheritance swift-extensions conform
1个回答
0
投票

我希望这会有所帮助。

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
© www.soinside.com 2019 - 2024. All rights reserved.