0

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;
}
}
hi there
  • 35
  • 3
  • I find this somewhat confusing. It would be easier to understand if you just provided a [mre] that demonstrated the problem using simple classes. And include all the classes required (remember it must compile). And for demos purposes, only one class need be public. Others can simply be placed in the same file below each other. – WJS Jan 24 '22 at 17:57
  • Yeah sorry @WJS I will try and do that! – hi there Jan 24 '22 at 18:00

2 Answers2

2

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.

Tarmo
  • 3,851
  • 2
  • 24
  • 41
1

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.

p.s. The community bot asked me to provide some more explaination, yet I dont think it is going to be much more clear then this answer: explaination

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 24 '22 at 19:48