以下代码非常没用,未经测试。它仅应解释问题。 我想从应用程序中隐藏实现类,但定义层次结构。
提供以下界面
public interface RowType {
Integer getSumFromHere();
}
public interface TableType {
List<RowType> getRows();
}
由
实施public class RowImpl implements RowType {
private Integer value = 0;
private RowImpl nextRow;
public RowImpl someFunctionNotInInterface() {
return nextRow;
}
@Override
public Integer getSumFromHere() {
return nextRow == null ? value : value + nextRow.getSumFromHere();
}
}
public class TableImpl implements TableType {
List<RowImpl> implList = new ArrayList<>();
public void doSomethingOnImpl (){
for(RowImpl row : implList) {
row.someFunctionNotInInterface();
}
}
@Override
public List<RowType> getRows() {
return implList;
}
}
getRows()的实现导致错误"cannot convert from List<RowImpl> to List<RowType>"
实际上,它保证了implList中的每个条目都可以通过RowType接口访问,因此可以正常工作。
我尝试了<? extends RowType>
,但这与TableType接口不兼容。
当然,我可以通过复制列表return new ArrayList<>(implList);
来简单地解决问题,但这与引用类所拥有的列表不同。
是否有解决方案,还是设计完全错误?
编辑:在TableImpl中添加了函数,该函数阐明了为什么列表是基于RowImpl而不是基于RowType构建的。
答案 0 :(得分:3)
implList
是List<RowImpl>
,并且应仅包含RowImpl
个实例。
例如,您返回的List<RowType>
有一个add(RowType)
方法,该方法可用于添加不是 RowType
的{{1}}个实例
由于这个原因,RowImpl
不是List<RowType>
的超类型,并且如果要返回它,则必须强制转换List<RowImpl>
。
同时,您应确保调用者未对其进行修改,以使其实际上只能包含implList
个实例。
Collections.unmodifiableList()方法可以完成这两项工作:
RowImpl
答案 1 :(得分:2)
最简单的解决方案可能只是类型转换列表元素:
TableType
但是,更好的解决方案可能涉及重新设计API,以使RowType
知道其所持有的getRows()
的类型。仅当您允许调用RowImpl
的代码来了解实现类public interface TableType<T extends RowType> {
List<T> getRows();
}
时,这才是好选择(否则,前面的解决方案是合适的)。
RowImpl
这样,您的实现类可以通过以这种方式实现此版本的接口来使用public class TableImpl implements TableType<RowImpl> {
List<RowImpl> implList = new ArrayList<>();
@Override
public List<RowImpl> getRows() {
return implList;
}
}
:
init_op = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init_op)
答案 2 :(得分:1)
您应该将通用类型更改为
List<RowType> implList = new ArrayList<>();
而不是:
List<RowImpl> implList = new ArrayList<>();
将元素插入List
时,可以保证其具有所需的类型。例如:
implList.add(new RowImpl());