Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call overridden methods in a subclass? Potential candidate for refactoring

Originally I had a design problem where I needed five subclasses of a superclass, where all but two would use the same generic method of doing things and the other two classes would need special handling. I wanted to avoid writing the method five times; two special cases and three identical ones.

So I had every class inherit SuperClass, and its doSomething() method, and had SubClassSpecial1 and SubClassSpecial2 override with their own doSomeThing method.

This was all fine until I wrote a method which looked something like

void fooBar(SuperClass obj) {
    obj.doSomething()
}

and it could be called as fooBar( new SubClassSpecial1() );

The problem is that the runtime class of the obj variable is now that of its superclass, and thus it will call the methods defined in the superclass. I could, of course, make an abstract doSometing() method in the superclass, and make each subclass implement its own version, but that would duplicate code in three of the classes. And I want to avoid doing that ...

I would lose any gain polymorphism gives if I had a lot of branching through

if(obj.getClass().getName() == "SubClassSpecial1" )  ((SubClassSpecial1) obj).doSomething()K;
else if ...

So what should I do in order to make the design more elegant and un-hackish?

like image 275
oligofren Avatar asked Nov 02 '09 14:11

oligofren


People also ask

How do you invoke an overridden superclass method from a subclass?

It is what overriding for. The overridden method shall not be accessible from outside of the classes at all. But you can call it within the child class itself. to call a super class method from within a sub class you can use the super keyword.

Does method must be override in the subclass?

Subclass must override methods that are declared abstract in the superclass, or the subclass itself must be abstract. Writing Abstract Classes and Methods discusses abstract classes and methods in detail.

Should a subclass override all methods from the superclass?

It depends on the type of Superclass, if it's an Abstract class you must override all your method. For concrete class, you only have to override what is required. And this is the fundamental of OOPs that your superclass's methods can be used by subclass.

Under what circumstances would a subclass need to override a superclass method?

When a method in a subclass has the same name, same parameters or signature, and same return type(or sub-type) as a method in its super-class, then the method in the subclass is said to override the method in the super-class.


3 Answers

I'm a bit confused by this part of your question:

Of course, what I wanted to do was have each object call its own version of doSomething(), but failed to realise that in order to do that, obj needed to be declared as one of the subclassed methods. And now it's a mess.

Ofcourse the declaration doesn't matter, the doSomething() method will always be invoked according to the runtime type of the class.

So I think what you were trying to do should work just fine, e.g. these declarations can all be used to pass to the foobar method:

SuperClass sc1 = new SubClassSpecial1();
SubClassSpecial2 sc2 = new SubClassSpecial2();
//etc..
like image 87
NickDK Avatar answered Sep 28 '22 14:09

NickDK


What you've described should work fine as is.

Is obj.doSomething() actually calling the superclass' implementation? If it is, you're not overriding it properly. Check that you haven't changed the signature in your overridden versions.

like image 42
Terry Wilcox Avatar answered Sep 28 '22 14:09

Terry Wilcox


When you have this:

void fooBar(SuperClass obj) {
    obj.doSomething();
}

then the compile-time type of obj is SuperClass. This means that the compiler is going to check that SuperClass has a doSomething() method.
At runtime you can substitute a subclass of SuperClass, this is the Liskov Substitution Principle. Method foobar() does not know, and should not know, what the runtime type of obj is, only that it derives from SuperClass and so doSomething() can be called.

As to your example:

fooBar( new SubClassSpecial1() );

In this case you happen to know that the runtime type of the parameter is SubClassSpecial1 which specifically overrides doSomething(). In all cases the right method is called.

A word about refactoring. You may want to consider refactoring your hierarchy.
Your base class SuperClass should define doSomething() as abstract. Your three classes that need the same implementation of doSomething() should inherit it from an intermediate base class which has that specific implementation. Your two special classes should inherit directly from SuperClass and have their own implementation of doSomething().

like image 40
quamrana Avatar answered Sep 28 '22 14:09

quamrana