Hi I have this piece of code that is not very well designed, but I'm not the owner of this code so I can't change it.
public interface Car{ // This is a marker interface. }
public class BigCar implements Car{
public boolean isVeryBig(){
return true;}
}
public class QuiteBigCar implements Car{
public boolean isVeryBig(boolean withHatchBack){
return true;}
}
public Pickup implements Car{
public boolean isVeryBig(boolean withHatchBack, boolean withRoofRack){
return true;}
}
You see the interface only exists to let me know that BigCar, QuiteBigCar and Pickup "is a" Car. Not very clever, but that's what I have to deal with.
Now I have a method that receives a Car as a param and will returned a mocked version of the car. I want the mock to make sure every time isVeryBig() is called, it will return false regardless of the method signature. The problem is I don't have a common interface for all isVeryBig() methods; they all have a different signature.
public Car mockMyCar(Car car){
Car mockedCar = mock(car);
when(mockedCar.isVeryBig()) <-- This wont work since the method doesn't exist on the interface
return mockedCar;
}
Yes, I could cast Car into their subclass but this is not an option for me as there is too many classes that implement Car, make a instanceOf check on all implementation would make the code very nasty and I don't control new implementations of Car in the future.
Any idea?
A few options, in order from least-hacky to most-hacky:
Acknowledge that mocking a Car here makes as little sense as mocking a Serializable, and that you should actually pick an implementation to mock. You won't have the same trouble mocking a concrete BigCar or Pickup, and you can run through a few different implementations in a few test cases.
Refactor to a common properly-polymorphic interface as TrustNoOne described, rather than using ersatz polymorphism the way you have here. I know you may have your hands tied, but whoever stumbles across this question next might not.
You can do something similar to what you're describing—matching methods by name instead of signature—by supplying a default Answer when you create the mock:
Car car = Mockito.mock(Car.class, new Answer<Object>() {
#Override public Object answer(InvocationOnMock invocation) {
if (invocation.getMethod().getName().equals("isVeryBig")) {
return false;
}
// Delegate to the default answer.
return Mockito.RETURNS_DEFAULTS.answer(invocation);
}
};
Bear in mind, though, that your particular situation (of being able to downcast to one of a variety of implementations with different signatures) may require use of the extraInterfaces feature to let Java downcast as needed, which makes this entire thing tricky and fragile. You'd probably be better off using one of the other above solutions instead.
Related
I have been studying abstract methods lately and I can't understand why do we need them?
I mean, after all, we are just overriding them. Do you know its just a declaration? Why do we need them?
Also, I tried understanding this from the internet and everywhere there's an explanation like imagine there's an abstract class human then there're its subclasses disabled and not disabled then the abstract function in human class walking() will contain different body or code. Now what I am saying is why don't we just create a function in the disabled and not disabled subclasses instead of overriding. Thus again back to the question in the first paragraph. Please explain it.
One of the most obvious uses of abstract methods is letting the abstract class call them from an implementation of other methods.
Here is an example:
class AbstractToy {
protected abstract String getName();
protected abstract String getSize();
public String getDescription() {
return "This is a really "+getSize()+" "+getName();
}
}
class ToyBear extends AbstractToy {
protected override String getName() { return "bear"; }
protected override String getSize() { return "big"; }
}
class ToyPenguin extends AbstractToy {
protected override String getName() { return "penguin"; }
protected override String getSize() { return "tiny"; }
}
Note how AbstractToy's implementation of getDescription is able to call getName and getSize, even though the definitions are in the subclasses. This is an instance of a well-known design pattern called Template Method.
The abstract method definition in a base type is a contract that guarantees that every concrete implementation of that type will have an implementation of that method.
Without it, the compiler wouldn't allow you to call that method on a reference of the base-type, because it couldn't guarantee that such a method will always be there.
So if you have
MyBaseClass x = getAnInstance();
x.doTheThing();
and MyBaseClass doesn't have a doTheThing method, then the compiler will tell you that it can't let you do that. By adding an abstract doTheThing method you guarantee that every concrete implementation that getAnInstance() can return has an implementation, which is good enough for the compiler, so it'll let you call that method.
Basically a more fundamental truth, that needs to be groked first is this:
You will have instances where the type of the variable is more general than the type of the value it holds. In simple cases you can just make the variable be the specific type:
MyDerivedClassA a = new MyDerivcedClassA();
In that case you could obviously call any method of MyDerivedClassA and wouldn't need any abstract methods in the base class.
But sometimes you want to do a thing with any MyBaseClass instance and you don't know what specific type it is:
public void doTheThingsForAll(Collection<? extends MyBaseClass> baseClassReferences) {
for (MyBaseClass myBaseReference : baseClassReferences) {
myBaseReference.doTheThing();
}
}
If your MyBaseClass didn't have the doTheThing abstract method, then the compiler wouldn't let you do that.
To continue with your example, at some point you might have a List of humans, and you don't really care whether they are disabled or not, all you care about is that you want to call the walking() method on them. In order to do that, the Human class needs to define a walking() method. However, you might not know how to implement that without knowing whether the human is or isn't disabled. So you leave the implementation to the inheriting classes.
There are some examples of how you'd use this in the other answers, so let me give some explanation of why you might do this.
First, one common rule of Object Oriented Design is that you should, in general, try to program to interfaces rather than specific implementations. This tends to improve the program's flexibility and maintainability if you need to change some behavior later. For example, in one program I wrote, we were writing data to CSV files. We later decided to switch to writing to Excel files instead. Programming to interfaces (rather than a specific implementation) made it a lot easier for us to make this change because we could just "drop in" a new class to write to Excel files in place of the class to write to CSV files.
You probably haven't studied this yet, but this is actually important for certain design patterns. A few notable examples of where this is potentially helpful are the Factory Pattern, the Strategy Pattern, and the State Pattern.
For context, a Design Pattern is a standard way of describing and documenting a solution to a known problem. If, for example, someone says "you should use the strategy pattern to solve this problem," this makes the general idea of how you should approach the problem clear.
Because sometimes we need a method that should behave differently in its instances.
For example, imagine a class Animal which contains a method Shout.
We are going to have different instances of this Animal class but we need to implement the method differently in some cases like below:
class Animal:
/**
different properties and methods
which are shared between all animals here
*/
...
method shout():
pass
class Dog extends Animal:
method shout():
makeDogVoice()
class Cat extends Animal:
method shout():
makeCatVoice()
dog = new Animal
cat = new Animal
dog.shout()
cat.shout()
So dog shouts like dogs, and cat shouts like cats! Without implementing the shared behaviors twice
There is a different behavior of shouting in these instances. So we need abstract classes.
Suppose you don't know about implementation and still want to declare a method then we can do that with the help of abstract modifier and making it an abstract method. For abstract method only declaration is available but not the implementation. Hence they should end with ;
Example:
public abstract void m1(); // this is correct
public abstract void m1(){ ... } // this is wrong
Advantage: By declaring abstract method in parent class we can provide guideline to child classes such that which methods are compulsory to implement.
Example:
abstract class Vehicle{
abstract int getNoOfWheels();
}
Class Bus extends Car{
public int getNoOfWheels(){
return 4;
}
}
If you want the short answer, think of this:
You have an abstract class Car.
You implement 2 classes that extend it, Ferrari and Mercedes.
Now:
What if you did one of the following, for the method drive(), common to all cars:
1) changed the visibility of the method,
2) changed the name of the method from driving to Driving,
3) changed the return type, from a boolean to an int
Think about it. It might not seem to make any difference right, because they are different implementations?
Wrong!
If I am iterating through an array of cars, I would have to call a different method for each type of car, thereby making this implementation of abstract useless.
Abstract classes are there to group classes with a common template, that share common properties. One way this helps would be the looping over the array:
Abstract methods ensure that all cars declare the same method,
and therefore, any object of a subclass of Car will have the method drive(), as defined in the abstract class, making the for loop mentioned easy to implement.
Hope this helps.
I'm not quite sure how to word this question, but hopefully the example will make it a bit more clear. I'm trying to figure out the best way to have one of the implemented abstract methods not be called (do nothing) and I'm curious if my current approach is at all somewhat right.
abstract class Vehicle {
void doSomething() {
if (this.getClass() instanceof Chevy) {
operateOnCar();
}
}
abstract void operateOnCar();
}
class Chevy extends Vehicle {
#Override
void operateOnCar() {
print("Doing something to a car")
}
}
class HarleyDavidson extends Vehicle {
#Override
void operateOnCar() {
throw Exception("This isn't a car")
}
}
The other approach I can think of is to have the HarleyDavidson class implement operateOnCar()but do absolutely nothing - i.e. an empty method body. Is that potentially better? Maybe neither of these are viable examples and I should reconsider my design. Thanks!
Edit: tried to make my example a bit more clear
I'm trying to figure out the best way to have one of the implemented
abstract methods not be called (do nothing)
Asserting that a method should not be called is totally different from asserting that it should do nothing. It is furthermore wrongheaded to define a method on the superclass, regardless of abstractness, that is not ok to call on any instance of any subclass. Thus, some variation on the "do nothing" alternative is a much better choice.
And what's so hard about a method doing nothing when it does not need even to provide a return value? This is a method that does nothing:
void isCar() {
// empty
}
I should also observe at this point a method named isCar would be expected by most Java programmers to return a boolean indicating whether the object on which it is invoked is a "car", whatever that means in context. It would come as a surprise that such a method is declared not to return anything, and perhaps an even bigger surprise that it writes to System.out.
You're blurring the responsibilities of your abstract class and its concrete implementations. This is evidenced by your doSomething method.
void doSomething() {
if (this.getClass() instanceof Chevy) {
operateOnCar();
}
}
Your abstract class shouldn't care what instance it is; only the Chevy class needs to do something with this.
This may be why you're getting mixed up with the operateOnCar method. A Car is a Vehicle, but not all Vehicles are Cars. You could have trucks, vans, locomotives, boats, planes...all of which are vehicles in their own right, but definitely wouldn't support an operateOnCar method.
It may be as simple as renaming your method. You can definitely operate or fix a vehicle. You just want to keep that as agnostic as possible at the higher levels of the inheritance chain.
If you make a class, than that class (including its derived classes) should only have properties/methods related to that class. If a property/method does not fit, it shouldn't be in a class.
So how you can put OperateOnCar somewhere: with the strategy pattern, which is a common design pattern.
Than you make an interface OperatableOnVehicle, with an operation OperateOnVehicle. For vehicle it will be implemented, for a HarleyDavidson it is not implemented.
Try to avoid to use the word 'car'.
There are many examples to be found on internet about the strategy pattern, so google for more information about it's background.
I think if object calling this method throws the following exception:
throw Exception("This method should only be called if the car is a chevy")
There would be better to print out that it's not a car. As the name of the method suggests, it should return boolean
Is Chevy a car? Yes it is - return true and inform about the result
Is HarleyDavidson a car? No, it is not - return false and inform as well
is for exampleBicycle a car? No, definitely not. Is it a vehicle? Yes. Is legitime to ask it whether it's a car? Why not?
By the way, have you considered the following hierarchy?
Vehicle <- Car <- Chevy
Vehicle <- (Motocycle ) <- HarleyDavidson
I'm looking for a solution, that allows to protect the default methods from inheritance. The easiest solution could be - extend from class and etc... but in my case it's not possible.
Can someone suggest how to solve this problem? Could there be any workarounds?
Atm I have following code, which needs to be reworked (if/any possible):
public interface MyInterface1 {
default boolean isA(Object obj) {
return (boolean) obj.equals("A") ? true : false;
}
default boolean isB(Object obj) {
return (boolean) obj.equals("B") ? true : false;
}
}
public class MyClass extends MyLogic implements MyInterface, MyInterface1 {
// this class allows to inherit methods from both interfaces,
// but from my perspective i'd like to use the methods from MyInterface1 as it is,
// with a 'protection' from inheritance. is that possible?
}
You seem to want a way to write your interface so that implementing classes cannot provide their own implementations of its default methods. There is no way to do this, and indeed it runs counter to the purpose of interfaces in general and default members in particular.
The point of default methods is to provide a way to add methods to existing interfaces without instantly breaking all their existing implementations. Generally speaking, this is a binary compatibility issue, not a functionality issue. There's no particular reason to suppose in general that default implementations can provide the intended functionality, but without them, even old code that doesn't rely on the new methods at all is incompatible with interface revisions that add methods.
I think you have a factoring issue. Rather than trying to force classes to provide a specific implementation of a specific method -- which cannot even refer to that class's members, except possibly others defined by the same interface -- you should provide the common methods in a class of their own. After all, since you want all classes involved to provide identical implementations, it doesn't matter which class's implementations you actually use. Moreover, there is therefore no particular usefulness in marking any given class as providing implementations of the well-known methods.
Example:
public class MyImplementation1 {
public static boolean isA(Object obj) {
return obj.equals("A");
}
public static isB(Object obj) {
return obj.equals("B");
}
}
// Wherever needed, use as MyImplementation1.isA(o), etc.
You can do this even if you want these pre-baked implementations to operate in terms of the other methods of your interface. In that case, just add an argument to the fixed methods that provides the object to operate on. Perhaps that's what the obj arguments in your example were supposed to be; in that case, this may be closer to what you're after:
public interface MyInterface3 {
public String someInterfaceMethod();
}
public class MyImplementation2 {
public static boolean isA(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("A");
}
public static boolean isB(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("B");
}
}
You can't. At least if you restrict yourself to a pure-java-compiler solution.
And the reason is because it was not designed to do that: the purpose is to add new methods to existing interface (like java.util.Collection) without breaking the implementations. That way, we have sort(), stream(), forEach() on Collection.
If you were to allow such thing (forbidding implementation), then it would means a change in the interface would result in a compilation error for implementation (because they would override the method, method that would been rendered final). That was not the purpose.
There are several other options to achieve that, depending on your need:
Abstract class with final method being the previously default method.
Testing the default behavior using unit testing.
Testing the possible implementation and check they don't override it.
The last case can probably be done easily with Reflections: you would have to list all implementations, and check for each interface's default method that there is no overriding using Reflections.
I take it you mean you want to write a class that uses the default methods of an interface, but does not inherit them.
In your example code, you attempted to use the default methods by implementing the interface. When you implement an interface, by design you also inherit all its methods. This is the Liskov Substitution Principle. By implementing the interface you are telling your users that all instances of your class are substitutable for instances of the interface. But if the interface default methods weren't inherited, this wouldn't be true, so you would be lying to users of your class.
To have your class use the interface's default methods without inheriting them, don't implement the interface! Instead, use a helper class that does:
public interface MyInterface1 {
default boolean isA(Object obj) {
return obj.equals("A"); // or "A".equals(obj) to avoid NullPointerException
}
default boolean isB(Object obj) {
return obj.equals("B");
}
}
public class MyClass extends MyLogic implements MyInterface {
private static class Helper implements MyInterface1 {
void doSomeWork() {
// do something that calls isA() and isB()...
}
}
public void someMethodOfMyClass() {
// ...
Helper.doSomeWork();
// ...
}
}
No, This is not possible due to the way java implements the interface (pun intended). For more information as to the reason for this, see the answers to this question Why is "final" not allowed in Java 8 interface methods?
However here are some other ways to guide a developer not to override a default method:
A source code comment
//Do not inherit please
A javadoc comment
I’m currently facing a design problem and would appreciate advice on how I could resolve it:
The problem
I will use an example to illustrate my problem note this is just an example:
Suppose you have an interface called Pass with methods listed:
public interface Pass {
public boolean hasPassedA();
public boolean hasPassedB();
public boolean hasPassedC();
}
Suppose you have a class which implement this interface called Assessor:
public class Assessor implements Pass{
// how should I implement this class ??
}
Finally Student class:
public class Student {
// some code that defines student behaviour not important.
}
The question is then how can I make the interaction between the Assessor and the student object a lot more flexible?
What I noticed is that an Assessor object should be something that is abstract because in reality there is no such thing as an Assessor, but instead you have different types of assessors such as a Math Assessor or English Assessor etc, which in turn will allow me to create different types of Assessor objects e.g.
MathAssessor extends Assessor
EnglishAssessor extends Assessor
The concept is that a Student can pass if all the methods declared in the Pass interface return true and all additional methods in the subjectAssessor classes return true.
What do I do in the Assessor class? I have read about adapter design patterns but haven’t fully grasped that notion or does it even apply to this situation?
To start, the Pass interface you have is not very flexible, which could make for difficulties. For example, what if one implementation of Pass only needs to have hasPassedA, or you have an implementation which needs hasPassedA, hasPassedB, hasPassedC and hasPassedD. Then the various types of assessors will need to figure out which pass conditions to check.
A more flexible way to do this might be to do something like this. Rather than having a Pass interface, maybe something like a Condition interface (the names of the classes/interfaces should be changed to make sense for your domain).
public interface Condition {
// true means the condition passed, false means it did not
boolean evalutate();
}
Now you could have a single Assessor class (I'm not sure if this is exactly how your assessor would work, but it's just a guideline):
public class Assessor {
boolean assess(Collection<Condition> conditions) {
for (Condition c : conditions) {
if (!c.evaluate()) {
return false;
}
}
// all conditions passed
return true;
}
}
Hopefully this helps for your problem.
First off, to answer your question about the adapter pattern, it doesn't apply here. You use the adapter pattern to add a layer between 2 incompatible systems to allow them to pass data back and forth.
Using your example, I would recommend writing default implementations of the hasPassed_() methods in Assessor, even if the implementation is nothing more than throwing a new UnsupportedOperationException (to answer the question about what if a particular Assessor only needs a subset of hasPassed_() methods you can just overwrite only the ones you need). You can modify the subject assessor's (e.g. MathAssessor, EnglishAssessor, etc.) Pass methods to be more specific or to provide additional checks before calling super.hasPassed_() (depending on your specific implementation).
For example suppose I have a class Vehicle and I wish for a subclass ConvertibleVehicle which has extra methods such as foldRoof(), turboMode(), foldFrontSeats() etc. I wish to instantiate as follows
Vehicle convertible = new ConvertibleVehicle()
so I still have access to common method such as openDoor(), startEngine() etc. How do I designed such a solution?
To clarify my two initial solutions, neither of which I am happy with are:
Have dummy methods foldRoof(), turboMode(), foldFrontSeats() which I override in ConvertibleVehicle only, leaving them to do nothing in other subclasses
Have abstract methods foldRoof(), turboMode(), foldFrontSeats() and force each subclass to provide an implementation even if it will be blank in all instances other than ConvertibleVehicle
The above seem slightly convoluted since they both pollute the base class as I add an increasing number of subclasses each with their own unique functions
After reading some of the responses perhaps there is some type of fundamental flaw in my design. Suppose I have a class VehicleFleet which takes vehicles and instructs them to drive as follows:
public VehicleFleet(Vehicle[] myVehicles) {
for (int i=0; i < myVehicles.length; i++) {
myVehicles[i].drive();
}
}
Suppose this works for dozens of subclasses of Vehicle but for ConvertibleVehicle I also want to fold the roof before driving. To do so I subclass VehicleFleet as follows:
public ConvertibleVehicleFleet(Vehicle[] myVehicles) {
for (int i=0; i < myVehicles.length; i++) {
myVehicles[i].foldRoof();
myVehicles[i].drive();
}
}
This leaves me with a messy function foldRoof() stuck in the base class where it doesn't really belong which is overridden only in the case of ConvertibleVehicle and does nothing in all the other cases. The solution works but seems very inelegant. Does this problem lend itself to a better architecture?
I'm using Java although I would hope that a general solution could be found that will work in any object oriented language and that I will not need to rely upon language specific quirks
Any objects that use Vehicle shouldn't know about ConvertibleVehicle and its specialized methods. In proper loosely coupled object-oriented design Driver would only know about the Vehicle interface. Driver might call startEngine() on a Vehicle, but it's up to subclasses of Vehicle to override startEngine() to handle varying implementations such as turning a key versus pushing a button.
Consider reviewing the following two links which should help to explain this concept:
http://en.wikipedia.org/wiki/Liskov_substitution_principle
http://en.wikipedia.org/wiki/Open/closed_principle
Consider posting a real world problem that you feel leads to the dilemma you describe here and someone will be more than happy to demonstrate a better approach.
I've done this in similar situations.
Option A)
If the specialized operations are part of the same sequence as a base operation ( e.g. ConvertibleVehicle needs to be foldRoof before it can drive ) then just put the specialized operation inside the base operation.
class Vehicle {
public abstract void drive();
}
class ConvertibleVehicle {
public void drive() {
this.foldRoof();
.... // drive
}
private void foldRoof() {
....
}
}
So the effect of driving a fleet will be some of them will fold their roof before being driven.
for( Vehicle v : vehicleFleet ) {
v.drive();
}
The specialized method is not exposed in the object public interface but is called when needed.
Option B)
If the specialized operation are not part of the same sequence and must be called under certain "special" circumstances then let a specialized version of a client call those specialized operations. Warning, this is not so pure nor low coupling but when both objects ( the client and the service ) are created by the same "condition" or builder then most of the times is ok.
class Vehicle {
public void drive() {
....
}
}
class ConvertibleVehicle extends Vehicle {
// specialized version may override base operation or may not.
public void drive() {
...
}
public void foldRoof() { // specialized operation
...
}
}
Almost the same as the previous example, only in this case foldRoof is public also.
The difference is that I need an specialized client:
// Client ( base handler )
public class FleetHandler {
public void handle( Vehicle [] fleet ) {
for( Vehicle v : fleet ) {
v.drive();
}
}
}
// Specialized client ( sophisticate handler that is )
public class RoofAwareFleetHandler extends FleetHandler {
public void handle( Vehicle [] fleet ) {
for( Vehicle v : fleet ) {
// there are two options.
// either all vehicles are ConvertibleVehicles (risky) then
((ConvertibleVehicles)v).foldRoof();
v.drive();
// Or.. only some of them are ( safer ) .
if( v instenceOf ConvertibleVehicle ) {
((ConvertibleVehicles)v).foldRoof();
}
v.drive();
}
}
}
That instaceof look kind of ugly there, but it may be inlined by modern vm.
The point here is that only the specialized client knows and can invoke the specialized methods. That is, only RoofAwareFleetHandler can invoke foldRoof() on ** ConvertibleVehicle**
The final code doesn't change ...
public class Main {
public static void main( String [] args ) {
FleetHandler fleetHandler = .....
Vehicles [] fleet = ....
fleetHandler.handle( fleet );
}
}
Of course, I always make sure the fleethandler and the array of Vehicles are compatible ( probably using abstrac factory or builder )
I hope this helps.
This is a good question. What it implies is that you have (or expect to have) code that asks a Vehicle to (for instance) foldRoof(). And that's a problem, because most vehicles shouldn't fold their roofs. Only code that knows it's dealing with a ConvertibleVehicle should call that method, which means it is a method that should be only in the ConvertibleVehicle class. It's better this way; as soon as you try to call Vehicle.foldRoof(), your editor will tell you it can't be done. Which means you either need to arrange your code so that you know you're dealing with a ConvertibleVehicle, or cancel the foldRoof() call.
I think most people are missing the point of Delta's question. It looks to me like he/she isn't asking about what inheritance is. He/She is asking about subclasses implementing functionality that is not a natural fit for a base class, and the resulting mess that can ensue. I.e. the pushing of specific methods / functionality up the hierarchy chain, or requiring that subclasses implement a contract for functionality that isn't a natural fit.
There is also the matter of whether it is valuable to be able to treat a base class like the subclass in every case (to avoid casting and use them interchangeably). *edit -- this is called the Liskov substitution principle (thanks for reminding me, Kyle).
This is just what subclassing does: adds functionality not present in a base class.
class MyVehicle : public Vehicle {
public:
void MyNewFunction()
...
There are two (really just) different flavors of inheritance: public and private, reflecting the Is-A and Has-A relationships respectively. With public inheritance, you're directly adding stuff to a class. If I have class Animal with methods Eat() and Walk(), I may make a subclass called Cat which has the method Purr(). A Cat then has public methods Eat, Walk, and Purr.
In the case of a Stack based on a LinkedList however, I may say that a Stack HAS-A LinkedList internally. As such, I do not expose any features of the base class publically, I retain them as private and have to explicitly offer whatever I choose as public. A list may have a method Insert(), but for the Stack, I restrict the implementation and rexpose it as Push(). No previous public methods are exposed.
In C++, this is defined by the access modifier given before the base class. Above, I'm using public inheritance. Here, I use private inheritance:
class MyVehicle : private Engine {
This reflects that MyVehicle HAS-An Engine.
Ultimately, subclassing takes everything available in the base class and adds new stuff to it.
EDIT:
With this new information it seems that you're really looking for, it seems, is interfaces as stated by an earlier (voted down) comment. This is one of the big problems with inheritance - granularity. One of C++'s big complaints is its implementation of multiple inheritance (an option to accomplish this.) Can you state specifically what language you're using so we can advise properly?
To add on to Kyle W. Cartmell's excellent answer, and to perhaps simplify Oscar Reyes's answer a tad...
You might want to consider having the base class define a method called prepareToDrive() where inherited classes could put any setup tasks that need to be done before starting up. Calling drive() would be the way to start everything up from the user's perspective, so we would need to refactor drive into a "setup" phase and a "go" phase.
public class Vehicle {
protected void prepareToDrive() {
// no-op in the base class
}
protected abstract void go();
public final void drive() {
prepareToDrive();
go();
}
}
Now, subclasses must implement the protected method go() (really bad method name, but you get the idea), which is where they do their class-specific handling of driving.
Now, your inherited class could look like this:
public class ConvertableVehicle extends Vehicle {
// override setup method
protected void prepareToDrive() {
foldRoof();
}
protected void go() {
// however this works
}
protected void foldRoof() {
// ... whatever ...
}
}
This structure would also help when you run into class TractorTrailerRig that needs to make sure the trailer is loaded and correctly attached before it can drive.
How does the user of Vehicle know its a ConvertibleVehicle? Either they need to dynamic cast to ensure it is correct, or you've provided a method in Vehicle to get the objects real type.
In the first case the user already has a ConvertibleVehicle as part of dynamic cast. They can just use the new pointer/reference to access ConvertiblVehicle's methods
In the second case where the user verifies the objects type with one of Vehicles methods they can just cast the Vehicle to ConvertibleVehicle and use it.
Generally, casting is a bad idea. Try to do everything with the base class pointer. Your car example doesn't work well because the methods are too low level, build higher level virtual functions.
All that said. I have needed to all a derived classes methods from the base class. I could have cast to the derived class but it was involved in a framework and would have required much more effort. The old adage "all problems can be solved with one more layer of indirection" is how I solved this. I called a virtual method in the base class with the 'name' of the function I wanted to call. 'Name' can be a string or an integer depending on your needs. It's slower, but you should only need to do it rarely, if you class hierarchy is expressive enough.
Having ConvertibleVehicle subclass Vehicle and add its own methods as you describe is perfectly fine. That part of the design is OK. The trouble you have is with fleet. ConvertibleFleet should not be a subclass of VehicleFleet. An example will show you why. Let's say VehicleFleet is like this:
public class VehicleFleet {
// other stuff...
public void add(Vehicle vehicle) {
// adds to collection...
}
}
This is perfectly fine and sensible, you can add any Vehicle or subclass of it to a VehicleFleet. Now, let's say we also have another kind of vehicle:
public class TruckVehicle extends Vehicle {
// truck-specific methods...
}
We can also add this to a VehicleFleet since it's a vehicle. The problem is this: if ConvertibleFleet is a subclass of VehicleFleet, that means we can also add trucks to ConvertibleFleet. That's wrong. A ConvertibleFleet is not a proper subclass, since an operation that's valid for its parent (adding a truck) is not valid for the child.
The typical solution is to use a type parameter:
public class VehicleFleet<T extends Vehicle> {
void add(T vehicle) {
// add to collection...
}
}
This will let you define fleets specific to certain vehicle types. Note that this also means there is no "base" VehicleFleet class that you can pass to functions that don't care what kind of vehicle the fleet has. This can be remedied using another layer of base class (or interface):
public interface VehicleFleetBase {
Vehicle find(String name);
// note that 'add' methods or methods that pass in vehicles to the fleet
// should *not* be in here
}
public class VehicleFleet<T extends Vehicle> {
void add(T vehicle) {
// add to collection...
}
Vehicle find(String name) {
// look up vehicle...
}
}
For methods that are pulling vehicles out of fleets and don't care what kind they are, you can pass around VehicleFleetBase. Methods that need to insert vehicles use VehicleFleet<T> which is safely strongly-typed.