So I have custom class that looks like this:
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;
}
}
Now I am writing another class here I need to call the above getPreviousActiveState() method:
public class Synapse<Cell> {
private Cell cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
this.cell.getPreviousActiveState; // <= CAN'T BE CALLED. WHY?
}
}
I know the problem has to do with the fact that I declared the class:
public class Synapse<Cell>
but I did this so that only a Synapse can only contain a subclass of Cell. For example I also have implemented a VisionCell, AudioCell, and Neuron class that all extend Cell. Was this use of generics unneccesary? If so, when should I use generics? Thanks!
Defining a type parameter called Cell
means is creating some confusion. Let's rename it to T
, and also add the pair of missing parenthesis to the this.cell.getPreviousActiveState
call:
class Synapse<T> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= CAN'T BE CALLED. WHY?
}
}
The error that you now get is: The method getPreviousActiveState() is undefined for the type T
Which is the compiler's way of telling you that no where in the code it guaranteed that type parameter T
has a getPreviousActiveState()
method. Note that Java generic are not like C++ templates: the generic class is compiled once independently of any calling site. In other words: the compiler does not check this class w.r.t to any particular instantiation, but rather it checks that it makes sense on its own.
In order to guarantee that T
has a getPreviousActiveState()
all you need to do is to specify an upper bound on T
that defines this method. We can use Cell
itself:
class Synapse<T extends Cell> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= Compiles!
}
}
Of course, you can make the code more versatile by introducing an interface defining the method(s) you're interested in and using this interface as the upper bound. You will also have to make Cell
implement this interface:
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!
}
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments