Java将方法参数定义为子类型

Mis*_*aze 1 java generics inheritance implementation wildcard

我想做的事

我有一个名为的接口strategy,它有一个方法strategise。该方法采用一个名为 的接口Entity作为参数。

public interface Strategy{

  void strategise(Entity entity);

}
Run Code Online (Sandbox Code Playgroud)
public interface Entity {
   void do_something();
}
Run Code Online (Sandbox Code Playgroud)

我有一个名为EntityImplImplements 的类EntityEntityImpl还有一个Entity没有的附加方法。

public class EntityImpl implements Entity{
    
    void do_something()         // defined in Entity interface
    void do_something_else()    // unique to Person

}
Run Code Online (Sandbox Code Playgroud)

我有另一个StrategyImpl实现strategy.

  • StrategyImpl期望将一个对象作为参数传递给它从:EntityImpl实现的函数。Strategystrategise
  • 这是因为调用了:中未定义的StrategyImpl.strategise()唯一方法。EntityImplEntitydo_something_else()
public class StrategyImpl implements Strategy {

  void strategise(Entity entity){
       entity.do_something_else();
  }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我尝试过做什么

  1. 如果我使用上面的代码,它将无法工作,因为entity.do_something_else()无法找到它,因为do_something_else它是唯一的EntityImpl且未在Entity.
public class StrategyImpl Strategy{

  void strategise(Entity entity){
       entity.do_something_else();
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 我尝试使用EntityImpl对象而不是Entity对象作为参数定义,StrategyImpl.strategise()但这不起作用,因为它认为我没有实现Entity.strategise()
public class StrategyImpl Strategy{

  void strategise(EntityImpl entity){
       EntityImpl.do_something_else();
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 我尝试过使用泛型和通配符,但我对java不熟悉。
public interface Strategy {

   void strategise((E implements Entity) entity);

}

Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激

谢谢你的时间!

Swe*_*per 5

你的设计有点缺陷,因为如果我这样做怎么办?

Strategy s = new StrategyImpl();
s.strategise(new SomeOtherEntity());
Run Code Online (Sandbox Code Playgroud)

这应该编译,因为s.strategise接受一个Entity并且SomeOtherEntity 一个Entity。但最终它将StrategyImpl.strategise被运行。它只能处理EntityImpl对象,不能SomeOtherEntity

您可以通过添加通用参数来解决此问题Strategy

interface Strategy<T extends Entity>{

    void strategise(T entity);

}

class StrategyImpl implements Strategy<EntityImpl>{

    public void strategise(EntityImpl entity){
        entity.do_something_else();
    }
} 
Run Code Online (Sandbox Code Playgroud)

这样, a与 aStrategy<EntityImpl>不同的类型Strategy<SomeOtherEntity>

这限制了您做一堆事情(无论如何您都不应该做),例如将一堆 General 放入Strategy集合中。Entity当您从该集合中取出一个时,谁知道该特定Strategy接受哪种类型Strategy

但是,您可以创建一个Strategy<? super X>whereX是 类型的集合Entity。该集合可以包含Strategy<AnySuperClassOfX>. 这是有效的,因为 pf PECS