Home > other >  Proper way to extend in java while changing variables
Proper way to extend in java while changing variables

Time:11-01

I am making simulations in java but i am having a hard time manipulating variables while extending.

To make the problem easier to express let's consider 2 Java classes Grid1 and Grid2.

Grid1

Class Grid1 {
    public int a;
    public int grid[];

    public Grid1(int a) {
       this.a=a;
       grid = new int[50];
    }
    
    public update() {
       for (int i : grid) {
           i =a;
       }
    }
}

Grid2

Class Grid2 extend Grid1 {

    public Grid2(int a) {
       super(a)
    }
    
    @Override
    public update() {
       for (int i : grid) {
           i =2*a;
       }
    }
}

Now let say i want to use Grid1 and Grid2 in the simulations. So i create two classes Sim1 and Sim2.

Sim1

Class Sim1 {
    public Grid1 grid1;

    public Sim1() {
       grid1 = new Grid1(10);
    }
    
    public draw() {
       draw_list(grid1); //lets say draw list is defined elsewhere
    }
}

Sim2

Class Sim2 extend Sim1{
    public Grid2 grid2;

    public Sim2() {
       grid2 = new Grid2(10);
    }
}

Now when i run update() in my main on Sim2 then draw_list i get the picture of Grid1 and not Grid2... So how can i fix this ? In other words i want to extend a class and change the type of the variable in the new extended class.

Thank you

PS: Actually the simulation are about conway game of life and the immigration automata. I want to extend immigration to be like conway ...

CodePudding user response:

All dogs are animals, right? Well, all Grid2 instances are also Grid1s. For the same reason: Grid2 extends Grid1 means: Grid2 is everything Grid1 defines, and more.

Thus, if you extend Sim1 you do not want to add a second field, because now your Sim2 has 2 fields. Instead, you want to end up assigning an instance of Grid2 to the field which is type Grid1. End up running Grid1 g = new Grid2(); which is perfectly legal java code, for the same reason Animal a = new Dog(); would be fine.

As written, your Grid1 class is dead in the water. You MUST call one of your parent class's constructors, and your Sim1 constructor makes a new Grid1 instance. Which you don't want when Grid2's constructor runs. We need to fix that, too. You've also slattered public all over this, that's not very nice.

class Sim1 {
  private Grid1 grid;

  public Sim1() {
    this(new Grid1(10));
  }

  protected Sim1(Grid1 grid) {
    this.grid = grid;
  }
  
  public draw() {
     draw_list(grid); //lets say draw list is defined elsewhere
  }
}
Class Sim2 extend Sim1 {
  public Sim2() {
    super(new Grid2(10));
  }
}

We now have 2 constructors; Sim2 can choose which one it wants to invoke, and we obviously invoke the one where we provide the ready-made Grid instance.

  • Related