Java中的泛型防止调用方法

时间:2013-07-20 20:29:53

标签: java generics composition

所以我有自定义类,如下所示:

public class Cell {
    protected boolean wasActive;

    public Cell() {
    this.wasActive = false;
    }

    public boolean getPreviousActiveState() {
    return this.wasActive;
    }

    public void setPreviousActiveState(boolean previousActiveState) {
    this.wasActive = previousActiveState;
    }
}

现在我在这里写另一个类我需要调用上面的getPreviousActiveState()方法:

public class Synapse<Cell> {
    private Cell cell;

    // some other methods... like isConnected

    public boolean getPreviousActiveState() {
    this.cell.getPreviousActiveState; // <= CAN'T BE CALLED. WHY?

    }
}

我知道这个问题与我宣布这个类的事实有关:

public class Synapse<Cell> 

但我这样做是为了只有一个Synapse只能包含一个Cell的子类。例如,我还实现了所有扩展Cell的VisionCell,AudioCell和Neuron类。这种泛型的使用是否不必要?如果是这样,我什么时候应该使用泛型?谢谢!

1 个答案:

答案 0 :(得分:3)

定义名为Cell的类型参数意味着产生一些混乱。我们将其重命名为T,并在this.cell.getPreviousActiveState调用中添加一对缺失的括号:

class Synapse<T> {
  private T cell;

  // some other methods... like isConnected

  public boolean getPreviousActiveState() {
    return this.cell.getPreviousActiveState(); // <= CAN'T BE CALLED. WHY?
  }
}

您现在得到的错误是: The method getPreviousActiveState() is undefined for the type T

编译器告诉你的方法是,在代码中没有保证类型参数T具有getPreviousActiveState()方法。请注意,Java generic不像C ++模板:泛型类独立于任何调用站点编译一次。换句话说:编译器不会将此类w.r.t检查到任何特定的实例,而是检查它是否有意义。

为了保证T具有getPreviousActiveState(),您需要做的就是在T上指定定义此方法的上限。我们可以使用Cell本身:

class Synapse<T extends Cell> {
  private T cell;

  // some other methods... like isConnected

  public boolean getPreviousActiveState() {
    return this.cell.getPreviousActiveState(); // <= Compiles!
  }
}

当然,您可以通过引入定义您感兴趣的方法的接口并使用此接口作为上限来使代码更通用。您还必须使Cell实现此接口:

interface ActiveStateProvider {
  public boolean getPreviousActiveState();  
}

class Cell implements ActiveStateProvider {
  protected boolean wasActive;

  public Cell() {
    this.wasActive = false;
  }

  public boolean getPreviousActiveState() {
    return this.wasActive;
  }

  public void setPreviousActiveState(boolean previousActiveState) {
    this.wasActive = previousActiveState;
  }
}

class Synapse<T extends ActiveStateProvider> {
  private T cell;

  // some other methods... like isConnected

  public boolean getPreviousActiveState() {
    return this.cell.getPreviousActiveState(); // <= Compiles!
  }
}