3

I would like to ask something about an issue i have. Lets say we have an interface called Vehicle.

Then we have a class that implements this interface called Car. Then another one called Bicycle.

Now the whole code uses these two objects (Car, Bicycle) and whenever needed interface Vehicle.

What if now i want to add a new attribute to Car class and due to this change also modify some of its methods. For example i can extend Car with a class called Car2. But now if i want to make use of Car2 in the code i will have to rewrite every single method and class that uses Car to a new class that will use Car2.

For example a method that does not belong to Car class.

int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

Now i want this method to be able to accept Car2 also and change the way it calculates its speed. Do i need to rewrite the class and method or is there an easier way to do it?

Keep in mind that i dont want to completely modify Car, i just want to have both Car and Car2 and use them on demand in the same classes without having to rewrite all of them.

Thanks!

2
  • If Car2 inherits from Car it is a Car itself Commented Nov 6, 2016 at 11:31
  • Did you manage to fix it? Commented Nov 6, 2016 at 12:27

6 Answers 6

2

You can override the methods of super class (Car) inside a sub class (Car2), which is called polymorphism, which is one of the core principles of OOP. This principle allows us to invoke different class behaviours depending upon the actual object (Car or Car2 object) passed at runtime.

For your problem, you can follow state pattern which will provide dynamic behavior depending upon the type passed and the actual implementation of checkSpeed(), as shown below:

SpeedChecker class:

public class SpeedChecker {
  int checkSpeed(Vehicle v) {
    //depending upon the Vehicle type object passed, checkSpeed() will be called
    v.checkSpeed();
 }
}

Car Class:

public Car implements Vehicle {
    int checkSpeed(Car c) {
       //Add specific logic for Car
    }
} 

Car2 Class:

public Car2 implements Vehicle {
    int checkSpeed(Car c) {
       //Add specific logic for Car2
    }
} 
Sign up to request clarification or add additional context in comments.

Comments

1

as Sami Kuhmonen says :

If Car2 inherits from Car it is a Car itself

I will detail. You said :

Now i want this method to be able to accept Car2 also and change the way it calculates its speed. Do i need to rewrite the class and method or is there an easier way to do it?

If you don't add methods but modify their content, you should reason by programming by interface or in more general way by programming by suitable common ancestor component. In Java, polymorphism allows not to type specifically an instance when you declare it if a base class or an interface is more suitable.

Here :

int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

you can send as parameter a Car or any subclasses of it, there a Car2.
So you should keep Car base class as declared type when it is suitable, especially in methods which may take the one or the other type.

It will work :

Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

It will not compile :

Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car2 c) {
    speed = c.attributeX * 100
}

6 Comments

If Car2 has an extra attribute called a1, will i be able to access it like this: c.a1, since c is passed as Car.
in OOP, you should avoid make public fields without good reason.
Lets say checkSpeed uses a method common to both Car and Car2. But since checkSpeed accepts a Car parameter, even if i pass a Car2 object it will still use the method in Car and not in Car2.
Not necessarily, if Car2 overrides the method declared in Car1, it is Car2 method which will be called
So if i use same methods in Car2 as in Car, overriding those in Car and casting parameters passed as Car to Car2 will be a good approach? Then if code at some point accepts a Car but i pass it a Car2 the code will not be aware that this is not a Car but it is a Car2 and just keep using same overridden methods.
|
0

You can check if the object Car c is actually of type Car2:

int checkSpeed(Car c) {
    if(c instanceof Car2){
        //do something if c is actually Car2, such as  
                   use attributes that exist in Car2 but not in Car
    else{
        //the regular case
        speed = c.attributeX * 100
    }
}

Comments

0

Keep in mind that i dont want to completely modify Car, i just want to have both Car and Car2 and use them on demand in the same classes without having to rewrite all of them.

You already have a broken design since your sample method violates the most important principle in OOP: information hiding. Refusing to fix that because it's a lot of work will cause much more work later, just as it is doing now. This extra work will grow exponentially and harm you deadlines...

For example a method that does not belong to Car class.

int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

Lets forget for a moment that this doesn't even compile...

Now i want this method to be able to accept Car2 also and change the way it calculates its speed. Do i need to rewrite the class and method or is there an easier way to do it?

If this method would be part of the Vehicle interface and implemented in Car (and Bicycle) you could simply implement it in Car2 any way you want. without changing anything else in your program.

And That's what OOP is all about. But you get that advantage only if you know and follow its principles...

2 Comments

Yes indeed, but this method was just a quick example. Dont think of this method like it belongs inside the class. Object indeed has its methods declared in the interface. Maybe it was a bad example from me, but think of it as a method that does not belong inside the class but uses Car and now i want it to also use Car2. Or do you mean that since it uses Car or Car2 it should have been inside the class all along?
@Ploo "Or do you mean that since it uses Car or Car2 it should have been inside the class all along?" exactly that.
0

Сlearer approach in this case would be letting the Vehicle object itself to determine how should speed be calculated. This makes sense since all information is needed to do that is already encapsulated in the Vehicle class.

What I mean is have an interface like that:

pulbic interface Vehicle {
     int getSpeed();
}

And implementations of the interface. For Car:

public class Car implements Vehicle {
// some car stuff
...
    @Override
    public int getSpeed() {
        return carspeed;
    }
...
}

And for Car2:

public class Car2 implements Vehicle {
// some car2 stuff
...
    @Override
    public int getSpeed() {
        return car2speed;
    }
...
}

Now your checker method can look like this:

public int checkSpeed(Vehicle v) {
    int speed = v.getSpeed();
    // do the checks
    ...
    return someResult;
}

This way you don't really need to know the type of the vehicle itself to be able to check its speed. This is the whole point of polymorphism.

And in case you can't modify existing interface, I would suggest you to extend original Vehicle interface with SpeedVehicle that contains all required methods, and build a class hierarchy based on it.

Comments

0

If Car2 is always a Car and needs all the behaviors of Car, then you need to make Car2 a inherit from Car. If Car2 is not always a Car, but they have common ground, then you need to determine what that common ground is, implement it as a BaseCar class or an ICar interface if the implementations totally differ and Car along with Car2 should be inherited from BaseCar/ICar.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.