8
$\begingroup$

Abstract classes are peculiar things. Consider:

public abstract class Shape {
    String name;
    protected Point startPoint;

    public Shape(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public abstract double getArea();
}

The classic way to explain them is to say that they are like interfaces, but can implement methods. But explaining this way seems counter to their essential nature, and forces us to devolve into a series of random-factoid comparisons between interfaces and Abstract classes. (Interestingly, the JavaDoc commits this particular sin.) At no point in that discussion do we even try to get at the intuitive heart of what abstract classes really are.

On the other hand, classes can also be declared "abstract" even if everything is fully implemented and there are no abstract methods at all, which the programmer can do simply to make sure that the class cannot be instantiated directly.

This lends itself to a different kind of explanation. We could say that "Abstract classes represent abstract ideas, so that means that we can't instantiate them, and they can declare methods that must be implemented by child-classes." But, of course, they can have constructor methods. This seems mysterious until you realize that they are instantiated during constructor-chaining, so saying that they can't ever be instantiated is really not true.

I can think of no explanation for abstract classes that really gets to their essential nature. Has anyone else found an elegant way to describe them?

$\endgroup$
1
  • $\begingroup$ Now there are default methods and static methods that can be in interfaces. This can often be an alternative to an abstract class, since you don't blow your inheritance when you implement it. $\endgroup$ Nov 20, 2021 at 20:12

6 Answers 6

8
$\begingroup$

The rules for abstract classes are the same as for other classes, with a few minor differences:

  • An abstract class may have methods that do not have a body
  • An abstract class has to be sub-classed, at some level, to a non-abstract class before you can instantiate an object
  • It is not legal to directly instantiate an object of an abstract class

With an abstract base class that has abstract methods, or methods without bodies, all of those methods must be implemented in the subclass, at some level, before instantiation of an object is allowed.

So, imagine the school's official letterhead. At the top is the school logo, name, address, and maybe their motto. Everyone sending an official letter from the school is supposed to use the same letterhead, and they should use the same style and format as other official letters. Sometimes it's allowed to add to the top, such as when the principal gets to add his name to the letterhead, but others are not supposed to do that. To make it easier for everyone to follow the same format at style, the secretary created a "sample" letter for everyone to use. Still some people just didn't get it right, especially the Athletics Department, who used a totally different letterhead. Finally, to end the problem the principle made one, perfect, letter. Instead of real information, however, he used place holders. It looks something like this:

The School of Choice        $School of Choice$          342-54-87971
15 Our Plaza, NE      $Best Students & Best Teachers$   342-54-87915 fax
Best Town, Milan              $Better Grades$           @school_of_choice

From: {your name here}                                     {today's date}

TO: {name of recipient}
    {address of recipient}
    {address line 2}

Subject: {subject goes here}


{your letter goes here

Mauris ut mattis dolor. Donec mollis arcu a augue varius, eu pharetra
ante gravida. Sed ut posuere mi, vitae luctus urna. Vestibulum porta, 
velit quis facilisis hendrerit, nibh magna faucibus urna, a pellentesque
arcu nisi a tortor. Suspendisse nec maximus lorem. Maecenas convallis 
lorem quis neque fringilla, sit amet fermentum justo rutrum. Maecenas.

Vivamus elementum consequat semper. Nullam consectetur nunc quis turpis 
scelerisque pellentesque. Proin blandit, nulla a imperdiet vestibulum, 
odio dui tempor neque, sit amet vehicula magna nibh in tortor. Fusce nec
sapien vitae nibh faucibus hendrerit. Nam fermentum egestas arcu in
vulputate. Proin vulputate metus libero.

}

                                                www.school-of-choice.edu

This "letter" is saved on the school's network where any faculty member can access it, but students cannot. (It wouldn't be right for students to send out "official" letters would it?) The "letter" is also made read only. When a teacher needs to send a note to your parents (oops!) they can Word and load this letter template. They cannot save the template because it's read-only, [it is an abstract letter] but they can save a copy of it with a new name [a subclass of the letter]. Still, if they just printed this, and mailed it, it would look really bad for the teacher [it is still an abstract letter]. In order to make the letter "legal" to send, all the {your name here} type things have to be replaced with real information [replace the abstract methods with real ones]. If the teacher's department has its own web page on the school's site, then it can replace the last line, www.school-of-choice.edu with the full page address www.school-of-choice.edu/comp-sci/ [override a base class method]. Now that everything is replaced it is "legal" to print the letter [instantiate it], and send it to your parents. (Yikes!).

$\endgroup$
2
  • 1
    $\begingroup$ Good high school example, and pretty rich. $\endgroup$
    – Ben I.
    Jun 10, 2017 at 14:25
  • $\begingroup$ a perfect analogy.. thanks a lot and lot.. :) $\endgroup$
    – Azima
    Jan 9, 2023 at 11:29
4
$\begingroup$

It all came about, because the creators of Java looked at C++ and saw that it did not implement multiple inheritance safely (where as it was repeated inheritance that was unsafe, but they did not realise. And it is just C++'s implementation that makes it difficult to do repeated inheritance safely), and so decided that multiple inheritance was unsafe. They therefore decided to not have multiple inheritance in Java.

They then used abstract classes and interfaces, in place of deferred classes.

A deferred class is one concept, but Java has two keywords interface and abstract to implement them. A deferred class is one that can not be instantiated; It may have zero or more abstract methods.

In Java when all of the methods are abstract, then we make it an interface, so as to allow multiple (interface) inheritance.

Therefore an analogy for an abstract class and for an interface is a deferred class.

An analogy for a deferred class is just a class that is not finished, but is useful to be inherited from (for reuse).

$\endgroup$
3
$\begingroup$

You can explain it like this:

Abstract classes are theoretical\conceptual blueprints for a building. When you want to create a concrete (no pun intended) blueprint out of the conceptual one, you are likely to make some modifications here and there, but essentially you'd be bound to the conceptual blueprints.

However, you did, in fact, create a blueprint using the conceptual idea, so in a way you did instantiate it when you created the child bluprints. This is the same with the classes: The abstract class isn't created, but a child is created and because of they way polymorphism works (a class extending another class effectively makes the child into the parent's type), you are in a way "instantiating" the abstract class.

This analogy gives the idea that by creating the child class, you instantiate the abstract class in constructor-chaining.

$\endgroup$
2
$\begingroup$

I tend to begin with an example of a class which allows us to share behaviors with related child classes for which there is no clear parent that you would want to use (your Shape class is a good example of this). The example I typically use is that of a Student class and an Instructor class, with a Person abstract that they can each inherit from.

We then talk about the mechanical details of abstracts, and how they differ from interfaces. To motivate how they relate to interfaces, and should be used differently, I tend to lean on the "is-a" nature of inheritance, rather than the behavior-oriented nature of interfaces. Talking about method implementation is no longer a good motivator, since as of Java 8, interfaces can implement default methods.

This illustrates practical and technical differences, while emphasizing how proper use of abstracts and interfaces plays into good application design.

$\endgroup$
1
  • $\begingroup$ That's an especially good point about Java8 - I didn't know that that change had happened. It sounds like we're almost back to the multiple inheritance problem, then. $\endgroup$
    – Ben I.
    Jun 10, 2017 at 13:45
2
$\begingroup$

You can think of it from the bottom-up perspective.

You're making a program for a fast-food restaurant. So you have a Hamburger class, a FrenchFry class, a Soda class, and so on.

Eventually, you realize that there are lots of similarities in all of those classes. They all have mass, calorie counts, prices, and so on. So it makes sense to have a parent class called Food where those common items can be defined once and inherited by all of the other classes.

Except, of course, one shouldn't be able to instantiate the Food class directly. Food items should belong to an identifiable subclass like Hamburger or FrenchFry. (Insert school cafeteria joke here.)

$\endgroup$
1
$\begingroup$

I'd try something like:

As we have seen, it can be useful to move common fields or methods to a common super type, so we have to write (and debug) it only once.

However, sometimes the common behavior is only a small part of an object that does not have a meaningful existence on its own. Java therefore allows us to declare abstract classes. Abstract classes are incomplete in that they do not have to implement all the methods they declare. As a consequence, they can not be instantiated on their own. However, if we implement the methods in a subclass, we can instantiate that one, and thereby use the shared code.

I'd gloss over people making classes abstract only to prevent their instantiation, as I consider it a questionable practice.

As for interfaces, how about:

While interfaces can be used to share a contract (public methods), classes can additionally share implementation (fields, constructors, and non-public members), but are less flexible for implementing classes (a class may implement many interfaces, but extend only a single class).

If you're feeling adventurous, you may expand on the diamond problem to explain the reason for this restriction, but that is probably too technical at this level.

$\endgroup$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.