价值类型混淆

时间:2016-12-28 15:15:20

标签: java swift class value-type

关于StackOverflow的第一个问题:)

几天前我开始在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;
    }
}

为了这个问题,我们不要在这里谈论私人,公共或通用。保持简单! 这是我在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来解释它,我会非常感激。如果没有,请保持简单,以便我可以绕过它:)

提前致谢!

1 个答案:

答案 0 :(得分:2)

欢迎使用Stack Overflow和Swift编程!

对Java代码的改进

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

  1. 尽可能使用静态初始值设定项。完成此操作后,您甚至不需要显式构造函数。
  2. 您的children变量的类型为List<Integer>,但我怀疑您的意思是List<Node>
  3. 为了比较,请不要创建新的Node。使用这种方法,如果bestChild()返回值为0的Node,则无法知道是否因为子列表为空,如果确实存在值{0}的Node是最高值。我会使用流API,但你可以手动实现这样的功能。
  4. 以下是最终结果:

    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: { $0.value < $1.value })
        }
    }
    

    Swift等同于过时的Java apporach

    这里是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解决方案中使用数组呢?