抽象类扩展返回类型

时间:2014-03-22 10:51:46

标签: java extend return-type

我有一个由另外两个类扩展的抽象类。在抽象类中,我有一个方法,这两个类以不同的方式实现。即使我不知道它是哪个具体类对象,我也希望能够使用该方法。有没有办法使返回类型与使用方法的方式相同而不是抽象类型?

使其更具体,抽象类的相关部分:

public abstract class State<abstarct> {


public abstract Set<State<?>> findNeighbors();

对于其他两个班级:

public class PuzzleState extends State<PuzzleState> {

    @Override
public Set<PuzzleState> findNeighbors() {
    // making the set
    // unrelevant to the question
    return set;
}

public class QueensState extends State<QueensState> {

@Override
public Set<QueensState> findNeighbors() {
    // making the set
    // unrelevant to the question
    return set;
}

现在它当然没有用。我只是认为国家可能正是我所寻找的,但它不是。有没有办法让它发挥作用?我希望findNeighbors()根据使用的方法返回Set或Set。我希望它是这样的,因为在程序的另一部分我有一个display()方法,它接收PuzzleState或QueensState作为输入并相应地显示它。

我不知道我的问题是否足够清楚,但基本上我只是想知道是否有办法根据类改变抽象方法的返回类型。

2 个答案:

答案 0 :(得分:1)

为什么State被声明为通用?这样做我没有看到任何特定的价值。如果你想要实现的只是从子类中返回具体的State,你也可以这样做:

abstract class State {
   public abstract Set<? extends State> findNeighbors();
}

然后您的子状态为:

class PuzzleState extends State {
@Override
public Set<PuzzleState> findNeighbors() {
    Set<PuzzleState> set = new HashSet<PuzzleState>();
    return set;
}
}

class QueensState extends State {
@Override
public Set<QueensState> findNeighbors() {
    Set<QueensState> set = new HashSet<QueensState>();
    return set;
}
 }

OP首次评论后编辑

  

我有用于显示的类,需要知道它是Puzzle状态还是Queen状态

如果您的处理逻辑依赖于具体类型的知识而无法根据抽象类型进行多态化 - 那么如果您想坚持SOLID设计原则,那很可能是设计问题/嗅觉。

您可以考虑重构代码中显示特定状态的部分,如下所示:

在每个具体State(例如PuzzleStateQueenState)中都有返回interface StateImage的逻辑,然后在gui中要渲染的部分州的视觉形式 - 使用interface ImageRenderer

abstract class State implements StateDisplayable{ public abstract Set<? extends State> findNeighbors(); }

class PuzzleState extends State {
@Override
public Set<PuzzleState> findNeighbors() {
    Set<PuzzleState> set = new HashSet<PuzzleState>();
    return set;
}

public Image getImage(){
    return new PuzzleStateImage();  // implement this for Puzzle !!
}

  }



class QueensState extends State {
@Override
public Set<QueensState> findNeighbors() {
    Set<QueensState> set = new HashSet<QueensState>();
    return set;
}

public Image getImage(){
    return new QueenStateImage();  // implement this for QueenState!!
}

}


abstract class Image {
     abstract void draw();
 }

class PuzzleStateImage extends Image {
void draw() {
    // knows what/how to render PuzzleState for a visual component
}
}



class QueenStateImage extends Image {
  void draw() {
    // knows what/how to render QueenStateImage for a visual component
  }
}



interface StateDisplayable {
    Image getImage();
}

interface StateRenderer {
    void draw(Image state);
}

然后在GUI代码中

void display(){
    StateRenderer renderer = null ; // instantiate 
    Set<? extends State> states = null; // get your states here ( this is a mix of Puzzle and Queen states - but you dont care about the concrete type )
    for(StateDisplayable state : states){
        Image stateImage = state.getImage();  // this could be Puzzle or Queen stateImage
        renderer.draw(stateImage);
    }
}

答案 1 :(得分:0)

您可以使用Enum使用的相同模式:

public abstract class State<T extends State<T>> {
  public abstract Set<T> findNeighbors();
}

这将按照State的第一级子类的要求工作,但如果你有第二级,例如

public class SudokuState extends PuzzleState

然后findNeighbors的{​​{1}}仍然需要返回SudokuState

Java允许协变返回类型覆盖,即子类可以覆盖超类方法并将返回类型更改为父类返回类型的子类型(您可以覆盖返回的方法)具有返回String的对象(例如),但泛型不是协变的 - Set<PuzzleState> Set<String>的子类型。