我想为不同的数据结构编写一些不同的算法(例如树,列表,数组......)。除方法参数外,数据结构的方法是90%相同的。
public class BinaryTreeNode<T> {
public T key;
public BinaryTreeNode<T> leftChild;
public BinaryTreeNode<T> rightChild;
public boolean find(BinaryTreeNode<T> root, T key) { /* implementation */ }
}
public class ListItem<T> {
public T key;
public ListItem<T> next;
public boolean find(ListItem<T> root, T key) { /* implementation */ }
}
为了不必单独编写每个方法,我做了一个抽象的DataStruct<T>
类
public abstract class DataStruct<T> {
/**
* finds the key in dataStruct
* @param dataStruct DataStruct to look for key
* @param key value of type T to find in dataStruct
* @return true if key is in dataStruct else false
*/
public abstract find(DataStruct<T> dataStruct, T key);
}
我让BinaryTreeNode<T>
和ListItem<T>
extend
DataStruct<T>
现在我的问题是访问类属性。我这样解决了:
public class ListItem<T> extends DataStruct<T> {
public T key;
public ListItem<T> next;
@Override
public boolean find(DataStruct<T> listItem, T key) {
ListItem<T> tmpListItem = (ListItem<T>) listItem;
while(tmpListItem.next != null) {
if(tmpListItem.key == key)
return true;
}
}
}
但它感觉编码不好,因为我必须创建一个临时ListItem<T>
来强制DataStruct<T>
来访问ListItem<T>
的类属性。
有更好的方法吗?
答案 0 :(得分:1)
由于find
方法不是static
方法,因此接受DataStruct<T>
对象并对该对象执行搜索并不合理。对自己进行搜索更有意义,这样就无需投射任何东西:
public boolean find(T key) {
ListItem<T> tmpListItem = this;
while(tmpListItem.next != null) {
if(tmpListItem.key.equals(key))
return true;
tmpListItem = tmpListItem.next;
}
}
现在,你的一些方法确实需要一个DataStruct<T>
参数,例如,你需要在ListItem
中实现这些方法只能实现ListItem
,它会有意义的是检查输入参数的类型,如果run-type错误则抛出异常(或返回false或任何有意义的东西)并执行强制转换。这是equals
等方法中的常见做法,它接受Object
并且通常要求运行时类型为特定类型。
例如:
public boolean find(DataStruct<T> listItem, T key) {
if (!(listItem instanceof ListItem)) {
// decide whether to return false or throw an exception
}
ListItem<T> tmpListItem = (ListItem<T>) listItem;
...
}