Swift generi c дерево конвертировать в int - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь создать узел, который будет использоваться с деревьями, и это класс узлов, который я создал с помощью шаблонов.

class TreeNode<T: Comparable, Randomizable> {
var object: T
var left: TreeNode?
var right: TreeNode?

init(object: T, left: TreeNode?, right: TreeNode?) {
    self.object = object
    self.left = left
    self.right = right
}
}

Теперь у меня есть другая функция, которая заполнит дерево случайным образом. целые числа.

class Tree<T: Comparable, Randomizable> {
var root: TreeNode<T, Randomizable>? = nil

func generateIntTree(depth: Int = 5, maxNumNodesPerLevel: Int = 2, minValue: Int = 0, maxValue: Int = 20) {
    root = TreeNode<Int, Int>.init(object: Int.random(in: minValue...maxValue), left: nil, right: nil)
}

Я получаю сообщение об ошибке: «Невозможно присвоить значение типа« TreeNode »для типа« TreeNode <_, _>? »

Следует ли вместо этого использовать Any? Но я все еще хочу сохранить мои расширения.

1 Ответ

1 голос
/ 16 января 2020

В дополнение к ошибкам T: Comparable, Randomizable и T: Comparable & Randomizable у вас также есть проблема с жестким кодированием Int.random(...) в присвоении root типа TreeNode<T>?. Такое присваивание допустимо только в том случае, если Int и T относятся к одному и тому же типу, что неверно в неограниченном обобщенном контексте c (например, объявление Tree<T>). Это верно только для условного расширения: extension Tree where T == Int

// Stubs to make it compile

public protocol Randomizable {}
extension Int: Randomizable {}

private class TreeNode<T: Comparable & Randomizable> {
    var object: T
    var left: TreeNode?
    var right: TreeNode?

    init(object: T, left: TreeNode?, right: TreeNode?) {
        self.object = object
        self.left = left
        self.right = right
    }
}

public class Tree<T: Comparable & Randomizable> {
    fileprivate var root: TreeNode<T>?

    fileprivate init(root: TreeNode<T>? = nil) { self.root = root }
}

extension Tree where T == Int {
    public func generateIntTree(
        depth: Int = 5,
        maxNumNodesPerLevel: Int = 2,
        minValue: Int = 0,
        maxValue: Int = 20
    ) -> Tree<Int> {
        return Tree(root:
            generateIntTree(
                depth: depth,
                maxNumNodesPerLevel: maxNumNodesPerLevel,
                minValue: minValue,
                maxValue: maxValue
            )
        )
    }

    private func generateIntTree(
        depth: Int = 5,
        maxNumNodesPerLevel: Int = 2,
        minValue: Int = 0,
        maxValue: Int = 20
    ) -> TreeNode<Int>? {
        if depth == 0 { return nil }
        let payload = Int.random(in: minValue...maxValue)

        return TreeNode(
            object: payload,
            left: generateIntTree(
                depth: depth - 1,
                minValue: minValue,
                maxValue: maxValue
            ),
            right: generateIntTree(
                depth: depth - 1,
                minValue: minValue,
                maxValue: maxValue
            )
        )
    }
}

Кроме того, не передавайте min / max Int значения, подобные этому. Как вы видите, это действительно неуклюже (всегда нужно обойти две разные вещи), и это подвержено ошибкам (вы не можете легко случайно назначить min, где max принадлежит, или наоборот). Range<T> существует. Используй это. Посмотрите, насколько приятнее становится:

extension Tree where T == Int {
    public func generateIntTree(
        depth: Int = 5,
        maxNumNodesPerLevel: Int = 2,
        valueRange: ClosedRange<Int> = 0...20
    ) -> Tree<Int> {
        return Tree(root:
            generateIntTree(
                depth: depth,
                maxNumNodesPerLevel: maxNumNodesPerLevel,
                valueRange: valueRange
            )
        )
    }

    private func generateIntTree(
        depth: Int = 5,
        maxNumNodesPerLevel: Int = 2,
        valueRange: ClosedRange<Int> = 0...20
    ) -> TreeNode<Int>? {
        if depth == 0 { return nil }
        let payload = Int.random(in: valueRange)

        return TreeNode(
            object: payload,
            left: generateIntTree(depth: depth - 1, valueRange: valueRange),
            right: generateIntTree(depth: depth - 1, valueRange: valueRange)
        )
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...