【问题标题】:Can I avoid explicit cast with "generics" or better "design patterns"?我可以避免使用“泛型”或更好的“设计模式”进行显式转换吗?
【发布时间】:2019-05-17 20:10:28
【问题描述】:

我有一个界面

public interface Query {

}

及其实现:

public class UserQuery implements Query {
// specific properties to query a user
}

还有另一个界面

public interface Queries{

protected void runQuery(Query q);
}

及其使用它的实现:

public UserQueries extends Queries{

@Override
protected void runQuery(Query q){

// can I avoid this explicit cast with generic type parameters or other design patterns?
// for example Query<UserQuery> ?
var uq = (UserQuery) q;
..

}

}

所有的作品,但是,我怎样才能避免runQuery(Query q) 的演员表(也许runQuery(Query&lt;T&gt; q))?

想象Query 的一组不同实现(UserQueryStoreQueryBalanceQuery 等 - 使用上面的解决方案,我必须在每个覆盖方法中进行显式转换,这有点尴尬。

对于上述用例,有没有更好的设计模式?

【问题讨论】:

  • 为什么要将q 转换为UserQuery
  • @rgettman 因为我想从 UserQuery 访问属性。
  • 在接口Query中,你必须有一个公共方法,如run,所有类都必须实现。然后,Queries 将调用run 并且实现必须处理所有事情。如果你在做强制转换,你不需要接口或者应该创建Queries 的特定实现来只运行UserQuery
  • 换一种说法:如果Queries可以处理普通的Query,但UserQueries不能处理普通的Query,那么UserQueries不应该是@987654345的子类型@,根据 Liskov 替换原则。 (LSP 基本上说一个子类型应该能够做它的父类型所做的一切,还有更多。)
  • @nimo23:如果不了解这些对象的更多语义,很难确定,但this answer I wrote for another related question 可能是您的选择。

标签: java generics design-patterns


【解决方案1】:

您可以将Queries 设为通用接口:

public interface Queries<Q extends Query> {

    protected void runQuery(Q q);
}

那么UserQueries可以使用特定类型Query

public class UserQueries implements Queries<UserQuery> {

    @Override
    protected void runQuery(UserQuery q) {
        // q is a UserQuery, no need to cast anything...
    }
}

【讨论】:

  • 完美:) 非常感谢。
  • 请注意,如果你走这条路,除非你知道它的类型参数是什么,否则你将无法使用原始的 Queries 对象(这相当于知道这个中的确切子类型方案)。如果您只有Queries&lt;?&gt;,则您可以合法传递给runQuery 的唯一值是null
  • @DanielPryden 好点。但是,对于这种用例,有没有更好的解决方案/设计模式?
  • @DanielPryden 在这里对,你只能传递null,但通常你可以将Queries&lt;?&gt; 传递给接受Queries&lt;T&gt; 的通用方法,因此读取 @ 987654333@ 并在理论上再次添加(如果Queries 会公开这样的操作)该实例;因此复制该元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多