值类型混淆

Value type confusion

我在 Whosebug 上的第一个问题 :)

我几天前开始学习 XCode 中的 Swift,但我在理解 Swift 中的值类型时遇到了一些困难。由于我对 Java 非常熟悉,我将在 Java 中解释我的问题。这是我想在 Swift.

中写的内容
class Node {
    public int value; 
    public List<Integer> children;
    public Node parent;

    public Node() {
        value = 0;
        children = new ArrayList<Integer>();
    }

    public Node bestChild() {
        Node result = new Node();
        for (child : this.children) {
            if (child.value > result.value)
                result = child;
        }
        return result;
    }
}

为了这个问题,这里先不说private,public,generic。保持简单! 这是我在 Swift.

中的尝试
public class Node {
    var value: Int
    var children: NSSet
    var parent: Node?

    public init() {
        self.value = 0
        children = NSSet()
    }

    public func bestChild() -> Node {
        var result = Node()
        for child in children {
            if (child.value > result.value) {      //error
                result = child                     //error
            }
        }
        return result
    }
}

if语句的条件和里面的行都有错误。 XCode 建议转换变量,但仍然没有解决错误。

if ((child as AnyObject).value > result.value) {
    result = child as! Node
}

由于 Java 是我唯一知道的语言,如果有人能用 Java 来解释它,我将不胜感激。如果没有,请保持简单,以便我全神贯注:)

提前致谢!

欢迎使用 Stack Overflow 和 Swift 编程!

对 Java 代码的改进

首先,我建议对 Java 代码进行一些修改。

  1. 尽可能使用静态初始值设定项。这样做之后,您甚至不需要显式构造函数。
  2. 您的 children 变量是 List<Integer> 类型,但我怀疑您的意思是 List<Node>.
  3. 不要为了比较而创建新的 Node。使用这种方法,如果 bestChild() returns 一个值为 0 的 Node,则无法知道那是否是因为子列表为空,或者是否真的存在 Node 值为 0,这是最高值。我会使用流 API,尽管您可以手动实现此类功能。

这是最终结果:

class Node {
    public int value;
    public List<Node> children = new ArrayList<>();
    public Node parent; // Unused?

    public Node bestChild() {
        // Modern, easy approach:
        return children
               .stream()
               .max((x, y) -> Integer.compare(x.value, y.value))
               .get();

        // Old, classic Java approach:
        /*
        int max = Integer.MIN_VALUE;
        Node maxNode = null;

        for (Node child : this.children) {
            if (max < child.value) {
                max = child.value;
                maxNode = child;
             }
        }

        return maxNode; */
    }
}

相当于Swift

下面是我在 Swift 中的写法。欢迎提出后续问题

class Node {
    let value = 0
    let children = [Node]()
    weak var parent: Node? // Unused?

    func bestChild() -> Node? {
        return children.max(by: { [=11=].value < .value })
    }
}

Swift 相当于过时的 Java 方法

这里是 Swift 对 bestChild 方法的过时 Java 方法的实现。这只是为了比较。 不要这样做!

func bestChild() -> Node? {
    var max = Int.min
    var maxNode: Node?

    for child in children {
        if max < child.value {
            max = child.value
            maxNode = child
        }
    }

    return maxNode
}

要解决您的解决方案尝试中的问题:

NSSetSwift,因为 HashSet(没有泛型类型参数,不是 HashSet<T>)是Java。它是 Foundation 库中的一种数据类型,是为 Objective-C 发明的。在 99.999% 的情况下,您不应该在 Swift 中使用它。 NSSet 充当一组 AnyObject。为了能够对集合中的对象调用 .value,您需要先手动将对象转换为 Node.

所有问题的解决方案是使用 Set<Int>,这是 Swift 的原生 Set 数据结构。虽然这提出了一个问题,但为什么在 swift 解决方案中使用 Set,而在 Java 解决方案中使用数组?