如何为List <接口>返回List <impl>

时间:2018-12-19 12:47:08

标签: java

以下代码非常没用,未经测试。它仅应解释问题。 我想从应用程序中隐藏实现类,但定义层次结构。

提供以下界面

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构建的。

3 个答案:

答案 0 :(得分:3)

implListList<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());