14

I understand what an abstract class is in OOP paradigm. Yeah an abstract class is an incomplete type, cannot be instantiated.

Subclasses of the abstract class can extend the superclass and so on, and call a method through using a base type variable. But that is what I don't get.

I was reading the book, and the author said using a Superclass variable to reference a subclass and calling a common method calls the correct method. And yeah that's true. For example this little code I wrote:

public class ObjectOne extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectOne\n" ;
    }
}



public class ObjectTwo extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectTwo\n" ;
    }
}


public class ObjectThree extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectThree\n" ;
    }
}


public class SuperObject {
    public String objectString()
    {
        return "SuperObject" ;      
    }
}

    import static java.lang.System.out ;
public class ControlClass {

    public static void main(String[] args)
    {
        SuperObject [] arr = {new ObjectOne(), new ObjectTwo(), new ObjectThree()} ;

        for(SuperObject elem:arr)
        {
            out.println(elem.objectString()) ;
        }
    }
}

Em, so when main executes the correct methods are called for the objects using just the reference type. My question is so what is the point of an abstract class? Polymorphism works regardless of whether the method or class is abstract. Unlike C++, polymorphism works only when you specify it. For Java, it works apparently all the time.

So I guess the abstract keyword or abstract concept is just to complete the inheritance hierarchy, make incomplete types impossible to instantiate, or is to promote good OOP practice? Can someone clarify thanks.

KV Prajapati
  • 93,659
  • 19
  • 148
  • 186
Lews Therin
  • 10,907
  • 4
  • 48
  • 72
  • 2
    Okay, well problem number one is that none of your classes in your example are declared as abstract. They are all concrete classes. I suspect that you need to reword your question, as I'm not sure you know what the difference is between an abstract class, an interface, and a non-final concrete implementation. – Jon Oct 11 '11 at 15:05
  • Um, that was the point. To show that polymorphism works without defining an abstract class/method. Guys, I'm reading your answers thanks. – Lews Therin Oct 11 '11 at 15:16
  • 2
    So your question is really "What is the point of allowing concrete classes to be extended?". Because you may want to add additional behaviour to an already implemented class, or you may wish to override the default behaviour. If you want to *prevent* this happening, then you can use the *final* keyword on the class that you don't want extended. – Jon Oct 11 '11 at 15:34
  • @Jon Sorry man, I was in class. I think I understand where my confusion stemmed from. In C++ I falsely believed that polymorphism was *dependent* on abstract classes. But that is wrong. I can use the *virtual* keyword to make polymorphism happen, but to make an abstract class I had to use a pure virtual function, simply because there is no abstract keyword in C++. The only difference in Java is polymorphism is implicit. There is more..if you are reading please wait... – Lews Therin Oct 11 '11 at 18:31
  • In the book I am reading, "The primary purpose of an abstract class is to provide an appropiate superclass from which other classes can inherit from and thus share a common design". I think that explanation is incomplete. From my example, obviously SuperObject is a superclass that creates a common interface among its subclasses. But it isn't abstract. So my understanding of it is, abstract classes are classes that it doesn't make sense to create objects from. To be continued.. – Lews Therin Oct 11 '11 at 18:36
  • Although you can declare the common methods of the abstract class in the subclasses without doing `abstract void draw()` in the abstract class, and polymorphism can still happen. The thing is if I wanted to use the base class to call the common methods, I would have to do a bloody typecast. Hence declaring the method abstract in the abstract base class makes sense. I don't know, if that's right. I'm just fumbling with it. But the real question I wanted to ask without knowing it..is polymorphism *dependent* on abstract classes. I don't think it is. Base classes just make it damn easier. – Lews Therin Oct 11 '11 at 18:39
  • 1
    On your last question, for *Java*, no, polymorphism is not dependent upon abstract classes. You could write a code base that didn't use interfaces or abstract classes at all, and it could still have polymorphic behaviour. This is bad practise, however, and generally speaking you should avoid extending non-abstract classes if you can possibly avoid it. You should also avoid deep inheritance hierarchies if you can, and prefer implementing interfaces to extending abstract classes when you can. – Jon Oct 12 '11 at 10:06
  • Also, have a read of the top answer here: http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface - you may find it helpful. – Jon Oct 12 '11 at 10:12
  • Jon, thanks. Sorry for late reply. I didn't know I got a response. You were very helpful and I appreciate it :) – Lews Therin Oct 15 '11 at 15:07

10 Answers10

17

I'm not sure you understand what an abstract class is, as none of the classes in your example are abstract, and nothing in there is an interface either. What you are doing is extending an instantiable class. Without the abstract keyword there is nothing to stop me doing:

SuperObject obj = new SuperObject();

I think a better example would be to illustrate how abstract classes are used. What they are commonly used to do is to provide a common method implementation. If a number of classes implement some interface, but all of them implement the same method in the same way using the same code, then what is commonly done is to create an abstract class that contains the common implementation, and get all of the concrete implementations to extend that class. This facilitates code reuse, and decreases the likelihood that one developer will change the common method implementation for one class, but forget the others. For example..

public class ObjectOne extends Thing {
  public String objectString()
  {
      return "objectString() of class ObjectOne\n" ;
  }
}

public class ObjectTwo extends Thing {
  public String objectString()
  {
    return "objectString() of class ObjectTwo\n" ;
  }
}

public class ObjectThree extends Thing {
  public String objectString()
  {
    return "objectString() of class ObjectThree\n" ;
  }
}

public abstract class Thing implements SuperObject {
  public String alwaysTheSame() {
    return "The same thing";
  }
}

public interface SuperObject {
  public String objectString();

  public String alwaysTheSame();
}

import static java.lang.System.out ;

public class ControlClass {

  public static void main(String[] args)
  {
    SuperObject [] arr = {new ObjectOne(), new ObjectTwo(), new ObjectThree()} ;

    for(SuperObject elem : arr)
    {
        out.println(elem.alwaysTheSame());
        out.println(elem.objectString()) ;
    }
  }
}

What we have done here is introduce an abstract class Thing, which provides a method implementation that is common to all 3 implementations of SuperObject (which is now an interface). This means we don't have to write the same code again in three different places in order to to fully implement the SuperObject interface in each one of our concrete classes.

In addition to this, you can also extend non final classes. You may wish to do this in order to override the default behaviour of one or methods on the concrete class, or to decorate the the class with additional methods. Of course, when you are designing a class hierarchy from scratch you don't stick concrete classes in it that then get extended by other classes, as it's generally considered a bad code smell. However, few of us work with totally new written-from-scratch codebases, and must adapt an exiting codebase to new requirements. Extending a concrete class is one tool in the toolbox to do this.

EDIT: Misunderstood what the OP was asking, but the last paragraph above is relevant.

Jon
  • 3,510
  • 6
  • 27
  • 32
11

Let's say you want to deploy an application on an Ipad, Android, Iphone and Desktop application. You work on an important part that will do 95% of the job in an abstract class. Then you create 4 other small classes that will implement the abstract method differently for each device.

That way, you won't repeat 95% of the work, and each device will instanciate his own class, that extends the abstract common class.

Nicolas Zozol
  • 6,910
  • 3
  • 50
  • 74
5

Abstract classes are an excellent way to create planned inheritance hierarchies. They're also a good choice for nonleaf classes in class hierarchies.

Here's a good detailed explanation: (extracted from here)

Choosing interfaces and abstract classes is not an either/or proposition. If you need to change your design, make it an interface. However, you may have abstract classes that provide some default behavior. Abstract classes are excellent candidates inside of application frameworks.

Abstract classes let you define some behaviors; they force your subclasses to provide others. For example, if you have an application framework, an abstract class may provide default services such as event and message handling. Those services allow your application to plug in to your application framework. However, there is some application-specific functionality that only your application can perform. Such functionality might include startup and shutdown tasks, which are often application-dependent. So instead of trying to define that behavior itself, the abstract base class can declare abstract shutdown and startup methods. The base class knows that it needs those methods, but an abstract class lets your class admit that it doesn't know how to perform those actions; it only knows that it must initiate the actions. When it is time to start up, the abstract class can call the startup method. When the base class calls this method, Java calls the method defined by the child class.

Community
  • 1
  • 1
Saket
  • 45,521
  • 12
  • 59
  • 79
2

You also don't have to implement certain methods in abstract classes. You can decide what have to be declared in Subclasses and what you want declare in the Superclass.

Look at OutputStream for example:

public abstract void write(int i) throws IOException;

public void write(byte abyte0[]) throws IOException {
    write(abyte0, 0, abyte0.length);
}

public void write(byte abyte0[], int i, int j) throws IOException {
    if(abyte0 == null)
        throw new NullPointerException();
    if(i < 0 || i > abyte0.length || j < 0 || i + j > abyte0.length || i + j < 0)
        throw new IndexOutOfBoundsException();
    if(j == 0)
        return;
    for(int k = 0; k < j; k++)
        write(abyte0[i + k]);
}

You have an abstract write method (because you don't knwo where the OutputStream is going to) but all other extra write methods are not abstract and forwarded to this methods. So you only have to declare one method in the Subclass and have some methods "extra" without having to implement it in every Subclass.

Tobias
  • 9,170
  • 3
  • 24
  • 30
1

You may want a class not to have any instances. For example assume you have a Person class and two classes derived from it Student and Teacher. In this case you may not want to have any objects created from Person class as it may not have any meaning for your program.

hevi
  • 2,432
  • 1
  • 32
  • 51
0

The "point" is to enforce a class hierarchy, potentially with some functionality provided by base class(es), and force some behavior to be implemented by sub-classes.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
0

You would use an abstract class in cases where you do want to specify certain behaviour but don't want anybody to instatiate it directly but having to subclass it.

Alexander Rühl
  • 6,769
  • 9
  • 53
  • 96
0

An abstract class can be full bodied or the skeleton for the subclass. You define your template in the abstract class and its left for the subclass to extend and implement the methods defined in the superclass.

gotomanners
  • 7,808
  • 1
  • 24
  • 39
0

So I guess the abstract keyword or abstract concept is just to complete the inheritance hierarchy, make incomplete types impossible to instantiate, or is to promote good OOP practice?

My answer is yes to everything that you said.

michael667
  • 3,241
  • 24
  • 32
0

Along with what others have said, you may be using a library written by someone else, where you don't have access to the source code, but want to change it's behavior.

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76