Closed. This question is opinion-based。它当前不接受答案。
想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
2年前关闭。
Improve this question
我在Java中为某些算法建模可绘制平面图。
我的基本 class 是:
和
这对于算法来说效果很好。为了绘制图形,我用位置扩展了节点类:
我的问题是可绘制边缘的类。我想写这样的东西:
但是我以前从未见过这样的设计。最重要的是,编译器需要为超类构造一个
有没有人意识到这一点?
或者,使用您提供的类,用您提到的构造函数和一些吸气剂扩展,组装成MCVE:
这里的关键点是:当您拥有
这在很多情况下都很方便,并且通常可以将关注点清晰地分开:当方法仅需对
当方法确实需要图形表示时,可以让它采用图形的优势:
考虑到您的问题特别是关于...的旁注或关键点
类变量:
使用您在此处绘制的当前设计,每个
考虑到其他
想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
2年前关闭。
Improve this question
我在Java中为某些算法建模可绘制平面图。
我的基本 class 是:
public class Node {
private String label;
}
和
public class Edge {
private Node node0;
private Node node1;
}
这对于算法来说效果很好。为了绘制图形,我用位置扩展了节点类:
public class GraphicalNode extends Node {
private int x;
private int y;
}
我的问题是可绘制边缘的类。我想写这样的东西:
public class GraphicalEdge extends Edge {
private GraphicalNode node0;
private GraphicalNode node1;
}
但是我以前从未见过这样的设计。最重要的是,编译器需要为超类构造一个
public GraphicalNode(Node node0, Node node1)
构造函数。有没有人意识到这一点?
最佳答案
也许我在这里误会了一些东西-投票将显示-但是...
这听起来像是使用Covariance的教科书示例。
如果您的Edge
类具有方法Node getNode()
,则可以在extends Edge
类中为此方法定义更特定的返回类型。例如:
class Node {}
class Edge {
Node getNode();
}
class GraphicalNode extends Node {}
class GraphicalEdge extends Edge {
// This really overrides the method, with a more specific return type!
@Override
GraphicalNode getNode();
}
或者,使用您提供的类,用您提到的构造函数和一些吸气剂扩展,组装成MCVE:
public class WhatIsCovariance
{
public static void main(String[] args)
{
Node n0 = new Node();
Node n1 = new Node();
Edge e0 = new Edge(n0, n1);
Node n = e0.getNode0(); // Works
GraphicalNode gn0 = new GraphicalNode();
GraphicalNode gn1 = new GraphicalNode();
GraphicalEdge ge0 = new GraphicalEdge(gn0, gn1);
GraphicalNode gn = ge0.getNode0(); // Works
}
}
class Node
{
private String label;
}
class Edge
{
private Node node0;
private Node node1;
Edge(Node node0, Node node1)
{
this.node0 = node0;
this.node1 = node1;
}
public Node getNode0()
{
return node0;
}
public Node getNode1()
{
return node1;
}
}
class GraphicalNode extends Node
{
private int x;
private int y;
}
class GraphicalEdge extends Edge
{
private GraphicalNode node0;
private GraphicalNode node1;
GraphicalEdge(GraphicalNode node0, GraphicalNode node1)
{
super(node0, node1);
this.node0 = node0;
this.node1 = node1;
}
@Override
public GraphicalNode getNode0()
{
return node0;
}
@Override
public GraphicalNode getNode1()
{
return node1;
}
}
这里的关键点是:当您拥有
Edge
类型的引用时,则只能从中获取Node
(即使该引用实际上指向的对象是和GraphicalEdge
)。仅当引用的类型为GraphicalEdge
时,您才能从中获取GraphicalNode
。这在很多情况下都很方便,并且通常可以将关注点清晰地分开:当方法仅需对
Edge
和Node
对象进行操作,而对它们的图形表示不感兴趣时,则可以使用基类编写其签名:void computeSomething(Edge edge) {
Node n0 = edge.getNode();
Node n1 = edge.getNode();
...
}
void run() {
GraphicialEdge e = new GraphicalEdge(...);
computeSomething(e);
}
当方法确实需要图形表示时,可以让它采用图形的优势:
void drawSomething(GraphicalEdge edge) {
GraphicalNode n0 = edge.getNode();
GraphicalNode n1 = edge.getNode();
...
}
void run() {
GraphicialEdge e = new GraphicalEdge(...);
computeSomething(e); // Works
drawSomething(e); // Works as well
Edge edge = e;
drawSomething(edge); // Does not work. A GraphicalEdge is required.
}
考虑到您的问题特别是关于...的旁注或关键点
类变量:
使用您在此处绘制的当前设计,每个
GraphicalEdge
都会将其节点存储两次-一次作为GraphicalNode
,一次作为简单的Node
。例如,可以通过将事物定义为接口来避免这种情况:interface Node {}
interface Edge {
Node getNode();
}
interface GraphicalNode extends Node {}
interface GraphicalEdge extends Edge {
@Override
GraphicalNode getNode();
}
class DefaultEdge implements GraphicalEdge { ... }
考虑到其他
Node
类型,将泛型用作wero suggested in his answer可以增加更多的自由度,甚至可以提供更简洁,更灵活的设计。例如,您稍后可能要引入类似ColoredGraphicalNode
的内容,而泛型类型参数可以很好地覆盖它。但这要付出更多方法方法签名的代价:以通用形式编写方法,该方法允许“路由”所需的类型信息可能会变得有些麻烦,具体取决于您要走多远。09-13 13:48