gpt4 book ai didi

java - 正确实现所有相等对象的属性

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:30:57 27 4
gpt4 key购买 nike

问题

考虑图的实现,SampleGraph<N> .考虑图形节点的实现,Node extends N , 正确覆盖 hashCodeequals反射(reflect)两个节点之间的逻辑相等性。

现在,假设我们要向节点添加一些属性p。这样的属性绑定(bind)到节点的逻辑实例,即 Node n1, n2 , n1.equals(n2)暗示p( n1 ) = p( n2 )

如果我简单地将属性添加为 Node 的字段类,这发生在我身上:

  • 我定义Node n1, n2这样 n1.equals(n2)但是n1 != n2
  • 我添加 n1n2图表:n1插入逻辑节点时,n2在插入边期间引用节点时。该图存储了这两个实例。
  • 稍后,我从图中检索节点(返回 n1)并将其属性 p 设置为某个值。后来,我遍历了图的所有边,并从其中一条边中检索节点(返回 n2)。未设置属性 p,导致我的模型出现逻辑错误。

总而言之,当前行为:

graph.addNode(n1) // n1 is added
graph.addEdge(n2,nOther) // graph stores n2
graph.queryForNode({query}) // n1 is returned
graph.queryForEdge({query}).sourceNode() // n2 is returned

问题

以下所有陈述对我来说似乎都是合理的。他们中没有一个能完全说服我,所以我正在寻找基于软件工程规范的最佳实践指南。

S1 - 图形实现很差。添加节点后,图形应始终在内部检查它是否具有相同节点的实例(equals 计算结果为真)。如果是这样,这样的实例应该始终是图形使用的唯一引用。

graph.addNode(n1) // n1 is added
graph.addEdge(n2,nOther) // graph internally checks that n2.equals(n1), doesn't store n2
graph.queryForNode({query}) // n1 is returned
graph.queryForEdge({query}).sourceNode() // n1 is returned

S2 - 假设图表的行为与 S1 中的一样是错误的。程序员应该注意始终将相同的节点实例传递给图形。

graph.addNode(n1) // n1 is added
graph.addEdge(n1,nOther) // the programmer uses n1 every time he refers to the node
graph.queryForNode({query}) // n1 is returned
graph.queryForEdge({query}).sourceNode() // n1 is returned

S3 - 该属性未以正确的方式实现。它应该是类外部的信息Node .一个集合,例如 HashMap<N, Property> , 会工作得很好,将不同的实例视为基于 hashCode 的同一对象.

HashMap<N, Property> properties;

graph.addNode(n1) // n1 is added
graph.addEdge(n2,nOther) // graph stores n2
graph.queryForNode({query}) // n1 is returned
graph.queryForEdge({query}).sourceNode() // n2 is returned

// get the property. Difference in instances does not matter
properties.get(n1)
properties.get(n2) //same property is returned

S4 - 与 S3 相同,但我们可以将实现隐藏在 Node 中,这样:

class Node {
private static HashMap<N, Property> properties;

public Property getProperty() {
return properties.get(this);
}
}

编辑:在Stephen C 之后为当前行为和暂定解决方案添加了代码片段的 answer .需要澄清的是,整个示例均来自使用来自开源 Java 项目的真实图形数据结构。

最佳答案

看来S1最有道理。一些 Graph 实现在内部使用 Set<Node> (或一些等效的)来存储节点。当然,使用类似 Set 的结构将确保没有重复的 Node s,其中 Node n1Node n2当且仅当 n1.equals(n2) 被认为是重复的.当然是执行Node应确保在比较两个实例时(即在实现 equals()hashCode() 时)考虑所有相关属性。

其他语句的一些问题:

S2,虽然可能是合理的,但产生了一个实现,其中负担落在了客户身上,以理解和防范内部 Graph 实现的潜在缺陷,这是设计不当的明显标志Graph 对象的 API。

S3 和 S4 看起来都很奇怪,虽然我可能不太了解情况。一般来说,如果一个Node保留一些数据,在类 Node 中定义一个成员变量似乎是完全合理的反射(reflect)这一点。为什么要区别对待这个额外的属性?

关于java - 正确实现所有相等对象的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56061004/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com