[英]Inheritance and generics
我有一个应用程序,在节点和边G(N,E)的图形上执行各种分析算法。 节点和边的属性随应用程序而变化,并根据图的类型和属性的性质形成继承层次结构。 例如,Node层次结构的根可以表示最一般的非定向循环图(NcgNode)。 NcgNode的子类可以表示有向循环图(DcgNode),然后是DagNode等。可以应用于DAG的算法与NCG的算法不同,但反之亦然。 树的根的关键行为是添加和检索图的相邻节点。 问题是如何在不创建“未经检查”的异常的情况下执行此操作?
代码的简洁版本可能如下所示:
import java.util.ArrayList;
import java.util.List;
public class NcgNode {
private List<NcgNode> nodeList_ = null;
private List<? extends NcgNode> nodeListSrc_ = null;
private List<? super NcgNode> nodeListSink_ = null;
public <N extends NcgNode> void addNode(N node) {
if (nodeList_ == null) {
nodeList_ = new ArrayList<NcgNode>();
nodeListSrc_ = nodeList_;
nodeListSink_ = nodeList_;
}
nodeListSink_.add(node);
}
@SuppressWarnings("unchecked")
// Any way to avoid this?
public <N extends NcgNode> N getNode(int n) {
if ((nodeList_ == null) || (n >= nodeList_.size()))
return null;
// causes unchecked warning:
return (N) nodeListSrc_.get(n);
}
}
class DcgNode extends NcgNode {
// enables DCG algorithms, etc
}
class DagNode extends DcgNode {
// enables DAG algorithms, etc.
}
有没有更好的方法来设计它?
只需让你的列表有类型NcgNode,例如
private List<NcgNode> nodeListSrc_ = null;
您仍然可以将NcgNode的子类放入这些列表中。
你应该这样做,如下所示。 具有在抽象类( NcgNode
)中定义的方法,在子类型上进行参数化。 因此,可以轻松编写addNode
和getNode
。 然后你将有特定的实现(我使用DcgNode
和DagNode
;不确定这是否是你想要的)是它的一个子类,参数化本身。 这允许您稍后(见下文)算法要求节点的子节点与节点的类型相同。
public abstract class NcgNode<N> {
private List<N> nodeList_ = null;
public void addNode(N node) {
if (nodeList_ == null) {
nodeList_ = new ArrayList<N>();
}
nodeList_.add(node);
}
// Any way to avoid this?
public N getNode(int n) {
if ((nodeList_ == null) || (n >= nodeList_.size()))
return null;
return nodeList_.get(n);
}
}
class DcgNode extends NcgNode<DcgNode> {
// enables DCG algorithms, etc
}
class DagNode extends NcgNode<DagNode> {
// enables DAG algorithms, etc.
}
//...
static <N extends NcgNode<N>> void someAlgorithm(N node) { }
你的想法DagNode
是的一个子类DcgNode
不能是安全的,因为如果一个DagNode
“是一个” DcgNode
,那么这意味着你可以把任何DcgNode
把它视为其子,这是不是你想要的。
修改你的方法如下:
public NcgNode getNode(int n) {
if ((nodeList_ == null) || (n >= nodeList_.size())) {
return null;
}
return (NcgNode) nodeListSrc_.get(n);
}
看看“自我约束的类型”。 (编辑:不确定我理解这里的下选票)
您的根类应该是抽象的,实际的节点类型N
应该是类的类型参数,如
public abstract class AbstractNode< N extends AbstractNode< N > > {
private List< N > nodeList_ = null;
public synchronized void addNode( N node ) {
if ( nodeList_ == null )
nodeList_ = new ArrayList< N >();
nodeList_.add(node);
}
public N getNode( int n ) {
if ( nodeList_ == null || n >= nodeList_.size() )
throw new NoSuchElementException();
return nodeList_.get( n );
}
}
然后,具体的子类可以将它们自己的类型提供为N.对于深层继承层次结构,请将“My Type”保持为另一个抽象类。
class NcgNode extends AbstractNode< NcgNode > {
}
abstract class AbstractDcgNode< N extends AbstractDcgNode< N > > extends AbstractNode< N > {
// enables DCG algorithms, etc
}
class DcgNode extends AbstractDcgNode< DcgNode > {
}
class DagNode extends AbstractDcgNode< DagNode > {
// enables DAG algorithms, etc
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.