0

Is it possible to override a class parameter in Java? I'm pretty sure it is not possible but...

public class Dad {
  protected Building home;

  public Dad() {
  }

  public Building getHome(){
     return this.home;
  }
}

public class Son extends Dad {
  protected Shack home;

  public Son () {
    super();
    this.home = new Shack();
  }
}

public Shack extends Building{
 (...)
}

Apparently, there is no problem in adding two paraters with the same name but i'm not sure the two parameters are "link" together..

When I'm calling the getHome() function from a Son object, it returns a null object. Which make sense because the Dad object has no initialised Building object. Even if Son has a initialise Shack object that extends Building class. (I don't know if I'm clear enough...)

A simple solution would be to simply initialise home with a Shack object and cast home in Shack whenever it is necessary. But I'd like to know if there is another way to do this.

M.Ferru
  • 400
  • 1
  • 6
  • 20

3 Answers3

1

Fields can't be overriden. In your case field from Son just hiding field from Dad:

Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. [...] Generally speaking, we don't recommend hiding fields as it makes code difficult to read.

The GetHome function declared into Dad class, so it can see only home instance form Dad which is null. You could access Dad's home as super.home from Son instance.

You could extract superclass or interface.

interface HasHome {
    Building getHome();
}

class Dad implements HasHome {
    protected Building home;

    public Dad() {
        this.home = new Building();
    }

    @Override
    public Building getHome(){
        return this.home;
    }
}

class Son implements HasHome { // Or extends Dad
    protected Shack home;

    public Son () {
        super();
        this.home = new Shack();
    }

    @Override
    public Shack getHome() {
        return home;
    }
}

There is another question which way to choose. More over, supertype can be generic, as @Lorelorelore shows.

ilinykhma
  • 980
  • 1
  • 8
  • 14
1

You should not re-declare fields with the same names in subclasses. This is because fields are hidden, not overridden.

The compiler won't complain about this, but there are two variables in this case. Dad.home is not being assigned by the constructor in Son. So new Son().getHome() will return null in this example, and that's because getHome() only knows about Dad.home.

From where you are, the best is just to remove the home property from Son, and better yet, make it private in Dad and pass its value from the subclass using constructor parameters.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
1

Maybe you should refactor those two classes with generics:

Abstract superclass:

public abstract class Person<T extends Building> {
    protected T home;

    public T getHome(){
        return this.home;
    }
}

Dad class:

public class Dad extends Person<Building> {

    public Dad() {
        home = new Building();
    }

}

Son class:

public class Son extends Person<Shack> {

    public Son () {
        home = new Shack();
    }

}

You can check if the home field has the correct type (and also not null) with a simple test:

public class SonAndDadTest {

    @Test
    public void sonTest(){
        Son son = new Son();
        Assert.assertNotNull(son.getHome());
        Assert.assertEquals(son.getHome().getClass(), Shack.class);
    }

    @Test
    public void dadTest(){
        Dad dad = new Dad();
        Assert.assertNotNull(dad.getHome());
        Assert.assertEquals(dad.getHome().getClass(), Building.class);
    }

}
Lorelorelore
  • 3,335
  • 8
  • 29
  • 40