【发布时间】:2015-11-24 06:43:10
【问题描述】:
我尝试创建一个定义树的类,其中树节点可以标记,并且标记由后代节点继承,基本上创建了事物的分类法。
然后我有了一个想法,有时标签不应该被继承(企鹅不能飞的异常),但我想为此创建一个单独的类,因为可能有一些应用程序处理异常的开销是浪费了。所以我创建了另一个类,NodeWithException。我希望这棵树具有相同类型的节点,但要像 Node 一样具有可扩展性。
我的问题在于
public class NodeWithException<TYPE_PARAM extends NodeWithException<?>>
它将引入原始类型。但如果我不放“?”在那里,我会陷入无限递归的兔子洞。有没有更优雅的解决方案可以避免使用原始类型?
代码可以在下面阅读或从这里下载:https://drive.google.com/file/d/0Bzgrcf36fidPWVlFdk9qdmdfT1E/view?usp=sharing
我的课:
Node.java
package tags_and_tax.model;
import java.util.HashSet;
import java.util.Set;
public class Node<TYPE_PARAM extends Node> {
TYPE_PARAM parent = null;
final Set<TYPE_PARAM> children = new HashSet<>();
final Set<Tag> tags = new HashSet<>();
public void addChild(TYPE_PARAM child){
child.setParent(this);
}
public void setParent(TYPE_PARAM newParent){
if (parent != null){
parent.children.remove(this);
}
parent = newParent;
newParent.children.add(this);
}
public Set<Tag> getAllTags(){
Set<Tag> result = new HashSet<>(tags);
TYPE_PARAM node = parent;
while(node != null){
result.addAll(node.tags);
node = (TYPE_PARAM) node.parent;
}
return result;
}
public Set<Tag> getTags(){
return tags;
}
}
NodeWithExceptions.java
package tags_and_tax.model;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
@SuppressWarnings("rawtypes")
public class NodeWithException<TYPE_PARAM extends NodeWithException<?>> extends Node<TYPE_PARAM> {
final Set<Tag> removeTags = new HashSet<>();
public Set<Tag> getRemoveTags() {
return removeTags;
}
@SuppressWarnings("unchecked")
@Override
public Set<Tag> getAllTags(){
Set<Tag> result = new HashSet<>(tags);
LinkedList<TYPE_PARAM> parents = new LinkedList<>();
parents.add((TYPE_PARAM) this);
TYPE_PARAM node = parent;
while(node != null){
parents.add(node);
node = (TYPE_PARAM) node.parent;
}
while(parents.size() > 0){
node = parents.removeLast();
result.addAll(node.tags);
result.removeAll(node.removeTags);
}
return result;
}
}
Tag.java(这不是很有趣,只是为了完整起见)
package tags_and_tax.model;
import java.util.HashMap;
import java.util.Map;
/**
* Should be a "singletons" i.e. no two instances with the same name. Why not
* use enums? Because they can't be created during runtime.
* */
public class Tag {
private final String name;
private final int id;
private static int idCounter = 0;
static Map<String, Tag> map = new HashMap<>();
private Tag(String name) {
this.name = name;
id = idCounter;
idCounter++;
}
public String getName() {
return name;
}
/** Only for debugging purposes (to see that things are really singletons.) */
public int getId() {
return id;
}
public static Tag getTag(Enum enum1) {
return getTag(enum1.name());
}
public static Tag getTag(String str) {
Tag result = map.get(str);
if (result == null) {
result = new Tag(str);
map.put(str, result);
}
return result;
}
/** Only needed if deserialization messes things up. */
@Override
public boolean equals(Object tag2) {
if (tag2 == null)
return false;
return name.equals(((Tag) tag2).name);
}
/* Generated by IDE */
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public String toString() {
return "name: " + name;
}
}
【问题讨论】:
-
注意:由于您发布了一些背景,一个足够清晰的问题,然后是代码转储,我回答了问题,忽略了背景和代码转储。所以我可能误解了这个问题。
标签: java generics architecture