1

In this application we have the Automovel class:

public class Automovel {
    private String marca;
    private String matricula;
    private String anoConstrucao;
    private Motor motor;
    private int preco = 0;
}

(with their builders, getters and setters) and there is a class called Motor that is an attribute of the Automovel class.

Motor Class:

private int potencia;

    public Motor() {}

    public Motor(int potencia){
        this.potencia = potencia;
    }

    public int getPotencia() {return this.potencia;}

    public void setPotencia(int potencia) {
        this.potencia = potencia
}

There are also 2 subclasses of this class (MotorEletrico and MotorCombustao):

Motor Elétrico:

public class MotorEletrico extends Motor {

    private int autonomia;
    public MotorEletrico() {}

    public MotorEletrico(int potencia, int autonomia) {
        super(potencia);
        this.autonomia = autonomia;
    }

    public int getAutonomia() {
        return autonomia;
    }

    public void setAutonomia(int autonomia) {
        this.autonomia = autonomia;
    }

}

Motor Combustão:

public class MotorCombustao extends Motor{

    private int cilindrada;
    private String combustivel;

    public MotorCombustao(){}

    public MotorCombustao(int potencia, int cilindrada, String combustivel){
        super(potencia);
        this.cilindrada = cilindrada;
        this.combustivel = combustivel;
    }

    public int getCilindrada(){
        return cilindrada;
    }

    public void setCilindrada(int cilindrada){
        this.cilindrada = cilindrada;
    }

    public String getCombustivel(){
        return combustivel;
    }

    public void setCombustivel(String combustivel){
        this.combustivel = combustivel;
    } 
}

I store a car with an X engine in an array of Automovel objects, but when I try to access the getters and setters of the subclass (MotorCombustao / MotorEletrico), only the gets and sets of the mother class (Motor) appears. My problem is that I can't access the getters and setters of the motor subclasses. Here's an example of what I tried:

Automovel arrayteste[] = new Automovel[49];

Motor motor1 = new MotorEletrico();
motor1.setPotencia(5);

Automovel automovel1 = new Automovel("Opel", "xx-12-xx", "2000", motor1, 2000);

arrayteste[0] = automovel1;

System.out.println(arrayteste[0].getMotor().getPotencia()); //Here, I can't Do .getAutonomia
Renato
  • 2,077
  • 1
  • 11
  • 22
  • What evidence do you have that you "can't Do .getAutonomia"? – Scott Hunter Feb 01 '20 at 14:33
  • my evidence is that when i put .getMotor().get it doesnt show any stu in MotorEletrico or MotorCombustao – Ruben Amorim Feb 01 '20 at 14:42
  • Stepping back a second, when you're following LSK like this `Parent obj = new Child();`, you'll be referring to an instance of Parent when invoking `obj`. Under the hood, it's still `Child` and can be cast to such, but the idea is to share common functionality in the parent class so you don't even need to downcast – Rogue Feb 01 '20 at 15:07

3 Answers3

3

Short answer

You need to cast

System.out.println(((MotorElettrico)(arrayteste[0].getMotor())).getAutonomia());

TL;DR

When you wrote

Motor motor1 = new MotorElettrico();

you are using polymorphism.

This is very useful when, for example you, have a list of Motor that contains more then one motor type and for all of this you want to print the potencia.

Then you can write something like this:

List<Motor> list = Arrays.asList(new MotorElectico(), new MotorCombustao());
// ----- some set

print(list);

where print method is something like this:

public void print(List<Motor> list){
    for(Motor m : list){
        System.out.println(String.format("Potencia %d", m.getPotencia()));
    }
}

This happens because a MotorElectico IS A Motor and upcasting (casting to supertype) is always allowed.

In your case, you have to do downcasting: you are telling to a compilator that arraytest[0].getMotor() contains a Motor but this Motor is actually a MotorElectrico: you are asking to compilator to trust you. If at compile-time arraytest[0].getMotor() should not be a MotorElectrico you'd get a ClassCastException.

Renato
  • 2,077
  • 1
  • 11
  • 22
1

You need to cast the reference of the parent class to the corresponding child class if you want to access a method which is not inherited from the parent class e.g. the method, getAutonomia() is not inherited from Motor and therefore, you need to cast the reference of Motor to MotorEletrico before you can access getAutonomia(). Some more useful code is given below:

public class Main {
    public static void main(String[] args) {
        Automovel arrayteste[] = new Automovel[2];
        Motor motor;

        motor = new MotorEletrico(5, 10);
        arrayteste[0] = new Automovel("Opel", "xx-12-xx", "2000", motor, 2000);

        motor = new MotorCombustao(7, 4, "xx-yy-zz");
        arrayteste[1] = new Automovel("Opel", "xx-08-xx", "1995", motor, 1995);

        for (Automovel automovel : arrayteste) {
            motor = automovel.getMotor();
            if (motor instanceof MotorEletrico) {
                System.out.println(((MotorEletrico) motor).getAutonomia());
            }
            if (automovel.getMotor() instanceof MotorCombustao) {
                System.out.println(((MotorCombustao) motor).getCilindrada());
                System.out.println(((MotorCombustao) motor).getCombustivel());
            }
        }
    }
}

Output:

10
4
xx-yy-zz

[Update: the following update is based on your comment]

Another way to iterate arrayteste is as given below:

for (int i = 0; i < arrayteste.length; i++) {
    if (arrayteste[i] != null) {
        motor = arrayteste[i].getMotor();
        if (motor instanceof MotorEletrico) {
            System.out.println(((MotorEletrico) motor).getAutonomia());
        }
        if (arrayteste[i].getMotor() instanceof MotorCombustao) {
            System.out.println(((MotorCombustao) motor).getCilindrada());
            System.out.println(((MotorCombustao) motor).getCombustivel());
        }
    }
}
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
-1

You are familiar with the Liskov substitution principle, I assume. If you don't know the type of motor, you can write a statement that asks each instance of the Automovel array arraytest[i] what class it is. For example:

    List<Automovel> arrayteste = new ArrayList<>();

    Motor motor1 = new MotorEletrico();
    motor1.setPotencia(5);

    Automovel automovel1 = new Automovel("Opel", "xx-12-xx", "2000", motor1, 2000);

    arrayteste.add(automovel1);

    Motor motor = new Motor();
    String motorClass;
    String[] motorTypes = {"MotorEletrico", "MotorCombustao"};
    Set<String> motorClasses = new HashSet<>(Arrays.asList(motorTypes));

    for (int i = 0; i < arrayteste.size(); i++)
    {
        motorClass = arrayteste.get(i).getMotor().getClass().getName();
        if (motorClasses.contains(motorClass))
        {
            if (motorClass.equals("MotorEletrico"))
            {
                motor = (MotorEletrico)(arrayteste.get(i).getMotor());
            }
            else if (motorClass.equals("MotorCombustao"))
            {
                motor = (MotorCombustao)(arrayteste.get(i).getMotor());
            }
            System.out.println("Automovel #" + i + " : " + motor.getPotencia());
        }
        else 
        {
            System.out.println("Não sei que classe de motor é esse . . .");
        }
     }
}

But it might be better to explore the class design more closely. Possibly try to use interfaces.

Trunk
  • 742
  • 9
  • 24