What is the point of an abstract class?
oop - Abstract class in Java - Stack Overflow
oop - What are some practical examples of abstract classes in java? - Stack Overflow
java - What are abstract classes and abstract methods? - Software Engineering Stack Exchange
Videos
I understand what an abstract class is and how it works, but I don't get the point.
My thinking is: If you are going to create undefined methods in the abstract class, only to define them in each sub-class, why create the abstract in the first place.
What is it that I'm missing?
An abstract class is a class which cannot be instantiated. An abstract class is used by creating an inheriting subclass that can be instantiated. An abstract class does a few things for the inheriting subclass:
- Define methods which can be used by the inheriting subclass.
- Define abstract methods which the inheriting subclass must implement.
- Provide a common interface which allows the subclass to be interchanged with all other subclasses.
Here's an example:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
Notice that "abstractMethod()" doesn't have any method body. Because of this, you can't do the following:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
There's no method that implements abstractMethod()! So there's no way for the JVM to know what it's supposed to do when it gets something like new ImplementingClass().abstractMethod().
Here's a correct ImplementingClass.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
Notice that you don't have to define implementedMethod() or finalMethod(). They were already defined by AbstractClass.
Here's another correct ImplementingClass.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
In this case, you have overridden implementedMethod().
However, because of the final keyword, the following is not possible.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
public void finalMethod() { System.out.print("ERROR!"); }
}
You can't do this because the implementation of finalMethod() in AbstractClass is marked as the final implementation of finalMethod(): no other implementations will be allowed, ever.
Now you can also implement an abstract class twice:
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("second abstractMethod()"); }
}
Now somewhere you could write another method.
public tryItOut()
{
ImplementingClass a = new ImplementingClass();
AbstractClass b = new ImplementingClass();
a.abstractMethod(); // prints "abstractMethod()"
a.implementedMethod(); // prints "Overridden!" <-- same
a.finalMethod(); // prints "finalMethod()"
b.abstractMethod(); // prints "abstractMethod()"
b.implementedMethod(); // prints "Overridden!" <-- same
b.finalMethod(); // prints "finalMethod()"
SecondImplementingClass c = new SecondImplementingClass();
AbstractClass d = new SecondImplementingClass();
c.abstractMethod(); // prints "second abstractMethod()"
c.implementedMethod(); // prints "implementedMethod()"
c.finalMethod(); // prints "finalMethod()"
d.abstractMethod(); // prints "second abstractMethod()"
d.implementedMethod(); // prints "implementedMethod()"
d.finalMethod(); // prints "finalMethod()"
}
Notice that even though we declared b an AbstractClass type, it displays "Overriden!". This is because the object we instantiated was actually an ImplementingClass, whose implementedMethod() is of course overridden. (You may have seen this referred to as polymorphism.)
If we wish to access a member specific to a particular subclass, we must cast down to that subclass first:
// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();
Lastly, you cannot do the following:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
Only one class can be extended at a time. If you need to extend multiple classes, they have to be interfaces. You can do this:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
Here's an example interface:
interface InterfaceA
{
void interfaceMethod();
}
This is basically the same as:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
The only difference is that the second way doesn't let the compiler know that it's actually an interface. This can be useful if you want people to only implement your interface and no others. However, as a general beginner rule of thumb, if your abstract class only has abstract methods, you should probably make it an interface.
The following is illegal:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
You cannot implement methods in an interface. This means that if you implement two different interfaces, the different methods in those interfaces can't collide. Since all the methods in an interface are abstract, you have to implement the method, and since your method is the only implementation in the inheritance tree, the compiler knows that it has to use your method.
A Java class becomes abstract under the following conditions:
1. At least one of the methods is marked as abstract:
public abstract void myMethod()
In that case the compiler forces you to mark the whole class as abstract.
2. The class is marked as abstract:
abstract class MyClass
As already said: If you have an abstract method the compiler forces you to mark the whole class as abstract. But even if you don't have any abstract method you can still mark the class as abstract.
Common use:
A common use of abstract classes is to provide an outline of a class similar like an interface does. But unlike an interface it can already provide functionality, i.e. some parts of the class are implemented and some parts are just outlined with a method declaration. ("abstract")
An abstract class cannot be instantiated, but you can create a concrete class based on an abstract class, which then can be instantiated. To do so you have to inherit from the abstract class and override the abstract methods, i.e. implement them.
Abstract classes are "half-implementations" of a class. They can be partially implemented with some generic functionality, but leave part of the implementation to the inheriting classes. You could have an abstract class called Animal that has implemented some generic behavior/values such as Age, Name, SetAge(...). You can also have methods that are not implemented (they are abstract), much like an interface.
Interfaces are simply contracts that specify behaviors that should be available for a class. You could have an interface such as IWalker that requires public method Walk(), but no specifics on how it is implemented.
Classes that are entirely abstract (all methods are abstract) are (almost) the same as interfaces (the major difference being they can contain fields and non-public abstract methods, which interfaces cannot). The difference is when you have an abstract class which contains a method which has some common functionality which will be the same for all derived children.
If you want to model a Filesystem, for example, you know that, regardless of the object type, you will have a path for an item. You'd want to have a common implementation for getting that path (no point in writing the same thing over and over again), and leave anything special for the children to implement.
First of all, the examples will be in C#. But I think you'll have no problem understanding it. So...
You CANNOT instantiate objects of an abstract class. You must have a subclass that derives from the class, if you want to instantiate it. But this probably won't help you since you may have come across that before.
So let's try an example.
Suppose you want to lose weight and your nutritionist asks you to track your food intake. When you go to her again, you can't tell her that you ate a "food". Although it's not wrong, since all food has calories, it is too "abstract" for her. So you need to tell her WHICH food.
So, if she were to code that... She'd have an abstract class Food.
abstract class Food
{
public int CaloriesPerPound { get; set; }
//...
}
Why? Because that wouldn't allow you to say "I ate a food".
{
Food fries = new Food(); //This won't even compile
}
So you need concrete classes:
class Fruit : Food
{
//Other stuff related only to fruits
}
class Bread : Food
{
//Other stuff related only to Bread
}
So you'll have to tell exactly which food it is.
{
Apple desert = new Apple(); //Now we are talking
}
But she still needs the food class, it is still interesting to her:
class Meal
{
public List<Food> Foods { get; set; }
//Other meal related stuff
public int TotalCalories()
{
int calories = 0;
foreach (Food food in Foods)
{
calories = calories + food.CaloriesPerPound * FoodQuantity;
}
return calories;
}
}
That's an example of when you need an abstract class. When you want to have a base class, but you don't want anyone creating an object of your class.
An abstract CAN have abstract methods. It doesn't need to. Is totally ok to have an abstract class without abstract methods. Speaking of which...
Abstract method is something that it's too broad. There's no similarities on how things work, so the classes that derive from your class that has an abstract method won't be able to call the super class implementation. And you're also forcing all the sub classes to implement their version of that method.
Let's try another example? An Animal Band Simulator. You'd have animals, and each one of them would make a sound. But those are very different "implementations", they have nothing in common A dog differs from a cat, a cat from an elephant, an elephant from a cricket. So you'd have an abstract method MakeSound.
class Animal
{
public abstract void MakeSound();
}
But, if you have an abstract method in your class, that makes the whole class abstract!
abstract class Animal
{
public abstract void MakeSound();
}
So the rest of the code might be:
class Dog : Animal
{
public void MakeSound()
{
//bark at the moon
}
}
class Cat : Animal
{
public void MakeSound()
{
//meowing for food
}
}
And the BAND!
class AnimalBand
{
public List<Animal> Animals { get; set; }
public void RockOn()
{
foreach (Animal animal in Animals)
{
animal.MakeSound();
}
}
}
So this is an example of when you use an abstract method.
I guess this is the essence. It may be a little forced/convoluted, but I think it gets the point across. Go back to the examples that didn't help you before and see if they make sense now.
I'm go out on a limb and say you're a beginner. This stuff may seem strange to you, and you may not see any benefit in using abstract classes.
It's ok. It's strange for almost all of us when we start. But in time, you'll learn to appreciate it.
An abstract class is a class that cannot be instantiated (i.e. new myAbstractClass()). It is used as a template for other classes to inherit.
An abstract method is a method in an abstract class that can be overridden (i.e. implemented) in a derived class.
The difference between an interface and an abstract class is that you can put functionality in an abstract class (i.e. ordinary or virtual methods) that can be utilized in the derived class, whereas an interface is just an empty template.