Home > other >  How do I access setter of a subclass without downcasting in my Java code?
How do I access setter of a subclass without downcasting in my Java code?

Time:01-25

I'm pretty new to programming, so please bare with me. I have made a Class Car through composition with an instance variable movable : CarMovable. The CarMovable abstract class is not included here but I have made subclasses from it (since cars "move" in slightly different ways depending on turbos and stuff, and I also want to try the "code to interfaces" idea). Now, I have one subclass TurboMovable which override all the abstract methods from the CarMovable class and more. As you can see in the TurboMovable, the speedFactor method depends on the boolean turboOn (whether turbo is on or off), but I cannot figure out how I can change the turboOn value of an object like Saab95 saab = new Saab95(4,Color.BLUE,"Saab95",true);, without doing downcasting like this: TurboMovable movable = (TurboMovable)saab.getMovable().setTurboOff();. I can't wrap my head around how I would accomplish this, although I feel it should be possible to do somehow. The turboOn variable is only needed in the speedFactor implementation in the TurboMovable class, and I wish to find out if I have missed something that could allow me to simply do saab.getMovable().setTurboOff(); or similar. First time posting a question about programming, so sorry if this is all difficult to understand or unclear, thanks in advance for any help!

-

public class Saab95 extends Car{
public Saab95 (int nrDoors, Color color, String modelName, boolean turboOn){
    super(nrDoors, color, modelName,  new TurboMovable(0, 700, 0, 0, CarMovable.Direction.WEST,turboOn));
}
}
public abstract class Car {

private final int nrDoors; // Number of doors on the car
private Color color; // Color of the car
private final String modelName; // The car model name
private final CarMovable movable;

public Car (int nrDoors, Color color, String modelName, CarMovable movable){
    this.nrDoors = nrDoors;
    this.color = color;
    this.modelName = modelName;
    this.movable = movable;
}
... getters and setters...
}
public class TurboMovable extends CarMovable {
private boolean turboOn ;

public TurboMovable(double currentSpeed, double enginePower, double x, double y, Direction dir, boolean turboOn) {
    super(currentSpeed, enginePower, x, y, dir);
    this.turboOn = turboOn;
}


@Override
public double speedFactor(){
    double turbo = 1;
    if(turboOn) turbo = 1.3;
    return getEnginePower() * 0.01 * turbo;
}

@Override
public void incrementSpeed(double amount){
    setCurrentSpeed(getCurrentSpeed()   speedFactor() * amount);
}

@Override
public void decrementSpeed(double amount){
    setCurrentSpeed(getCurrentSpeed() - speedFactor() * amount);
}


public void setTurboOn(){
    turboOn = true;
}
public void setTurboOff(){
    turboOn = false;
}
}

CodePudding user response:

You can not do it and you should not do it. Whole point of abstraction is that whoever uses your code, gets a Car and should not care if the car has a turbo or not. Car having a turbo and specially switching it on or off is an implementation detail. Implementation details should be handled in the class itself. So let's say switching turbo on is a side effect of acceleration. All cars accelerate. Therefor Car has a function accelerate() and if it happens to be a TurboCar then one line in the implementation of accelerate() is setTurboOn(). Now turbo is switched on when car user accelerates without even knowing it. That's the whole point.

If you find that you need to cast to switch implementation details then you've designed your code wrong.

CodePudding user response:

Why not go for something like this:

Turbo turbo = new Turbo(speed/model what ever   boolean isactivated)

@Override
public void incrementSpeed(double amount){
    if(turbo != null)
        if(turboActive)
            speed = speed*turbo.increment

    setCurrentSpeed(getCurrentSpeed()   speedFactor() * amount);
}

@Override
public void decrementSpeed(double amount){
    if(turbo != null)
        if(turboActive)
            speed = speed*turbo.increment

    setCurrentSpeed(getCurrentSpeed() - speedFactor() * amount);
}


public void setTurboOn(){
    if(turbo != null)
    turboActive = true;
}
public void setTurboOff(){
    if(turbo != null)
    turboActive = flase;
}
}

If you dont want to cast, the program will never know that it has that specific method.

  •  Tags:  
  • Related