- We've defined several different types of spaceships for our game. The starfighter, the cargo shuttle - and the warp cruiser. Weeeee. - And all three of those inherit from the same common superclass called spaceship. We'll use those three subclasses to instantiate objects for each specific type of ship but we'll never actually need to instantiate the generic concept of a spaceship. In this case, spaceship can be defined as an abstract class because it exists purely for the sake of being inherited by other classes to provide some shared behavior but an abstract class itself can never be instantiated because it contains at least one abstract method which is a method that's declared with a method signature but not actually implemented in the abstract class.
That's deferred to any subclasses that inherit from the abstract class. They're responsible for actually implementing the abstract methods. In uml diagrams we identify spaceship as an abstract class by using italicized font. Now, not every method in an abstract class has to be abstract. The abstract class can have a mix of abstract methods and methods that it actually implements. If all three of our ship types have shields that work the exact same way, rather than making them each implement the same set shield method, we'll implement it once in the spaceship class and they'll all inherit it.
But, if each type of ship moves in a different way then each subclass will need to implement its own unique move method. So, we'll declare an abstract move method in our spaceship class. Again, italics are used to indicate that it's abstract and that abstract method serves as a sort of placeholder for each of the subclasses to let them know that they'll need to individually implement it And of course, each of the subclasses are free to implement any additional methods that are unique to them.
Some languages like Java or C sharp let you explicitly mark a class as abstract when declaring it which prevents the language from allowing that class to be instantiated. You must inherit from it with another subclass, implement the abstract methods in that subclass and then you can use that subclass to actually instantiate an object. In Java, you can also mark classes as final which has the opposite effect of abstract. A final class is meant to be instantiated and cannot be extended or inherited from.
This is often referred to as a concrete class because it implements any missing functionality from the abstract class. Now, not all languages have official keywords to identify abstract and concrete classes and you can treat a class as if it were abstract simply by omission, just don't create an object from it. In fact, we could write our Java code without ever formally marking classes as abstract and it would work just fine. The benefit of including keywords like abstract and final is to communicate your intentions for a class to other programmers. It let's them know whether or not a class was designed with inheritance in mind.
- Object-oriented basics: objects, classes, and more
- Defining requirements
- Identifying use cases, actors, and scenarios
- Domain modeling
- Identifying class responsibilities and relationships
- Creating class diagrams
- Using abstract classes
- Working with inheritance
- Developing software with object-oriented design principles