This article is from “LoulanPlan” by Bert.
The purpose of this article is to discuss the functions, examples, and usage scenarios of abstract classes and interfaces, which are my understanding and summary. More on the concepts of interfaces and abstract classes can be found in the documentation.
1. Abstract classes and their role
Abstract classes, as the name suggests, are abstractions of classes.
When introducing object-oriented concepts, we know that classes are abstractions of objective things, and abstract classes are further abstractions of classes. What should we understand?
For example, we define several classes of Class BMW, Class Benz and Class Audi to abstract the objective objects “BMW”, “Benz” and “Audi” respectively, including related attributes and behaviors (methods). However, as we all know, cars have universal attributes and behaviors, such as brand, engine, steering wheel, tire and other attributes, as well as forward, backward and turn behaviors. Therefore, we can further abstract the “automobile” class Car from BMW, Mercedes and other automobiles, which contains universal characteristics (attributes and methods). BMW, Benz, Audi and others inherit the abstract class extends Car to have the general characteristics of a Car. Then they define their special properties and methods based on the abstract class.
Abstract class Car is used to capture the general properties of subclasses, including properties and behaviors.
2. Interfaces and their functions
Let’s take a look at the interface. If I develop a flying car “Bote-Royce”, it will be defined as follows in the program:
class BoteRoyce extends Car {
/ /... Omit common features
/** * can fly */
void fly(a) {
System.out.println("Pretend to fly."); }}Copy the code
Looks fine:
BoteRoyce extends Car
This is a car.fly()
Method: Show that the car can fly.
However, as technology develops and there are many manufacturers that can build flying cars, does every flying car define a fly() method?
Abstract void fly() : void fly() : void fly() : void fly() : void fly()
No No No… Just as not all milk is called Terenzu, not all cars can fly, and flight is not a universal feature of cars. Defining the fly() method in Car clearly violates the principle that abstract classes are used to capture the general characteristics of subclasses.
In this scenario, one solution is to use interfaces, as follows:
/** ** Aircraft interface */
public interface Aircraft {
// Define abstract methods
void fly(a);
}
Copy the code
The definition of the BoteRoyce class is modified as follows:
/* * Implements the Aircraft interface, indicating that it has Aircraft capability */
class BoteRoyce extends Car implements Aircraft {
/** * overwrite interface methods to achieve flight capabilities */
@Override
void fly(a) {
System.out.println("Pretend to fly."); }}Copy the code
There are other flying cars that implement Aircraft through extends Car.
The interface Aircraft defined above is the interface. We usually use the interface to abstract the behavior.
3. The difference between interfaces and abstract classes
The difference between the two can be combined with the previous example to deepen the understanding.
An abstract class is an abstraction of the essence of a class, expressing the relationship is A, for example: BMW is a Car. Abstract class contains and implements the general features of the subclass, and abstracts the differentiated features of the subclass to be implemented by the subclass.
An interface is an abstraction of behavior that expresses a like A relationship. For example: Bote-royce like a Aircraft (it can fly like an Aircraft) but is essentially a Car. The core of an interface is to define the behavior, that is, what the implementation class can do, regardless of who the implementation class body is or how it is implemented.
4. Usage scenarios of interfaces and abstract classes
Those familiar with Java might suspect that the above use of the interface could be implemented by abstracting Car again:
/** ** flying car */
abstract class FlyCar extends Car {
// Define abstract methods
public abstract void fly(a);
}
Copy the code
A normal Car extends Car, but a flying Car extends FlyCar:
/* * Inherits FlyCar, which is a flying car */
class BoteRoyce extends FlyCar {
/** * overwrite abstract methods to achieve flight capabilities */
@Override
public void fly(a) {
System.out.println("Pretend to fly."); }}Copy the code
If you think the same way, you get the point of the abstract class. But then again, isn’t there no point in the interface?
Of course not. As far as BoteRoyce is concerned, if you’re concerned with flying cars as a whole, defining the abstract class FlyCar is a good choice; If you are concerned about the “flying” behavior of the car, you might as well continue to use the Aircraft interface scheme above.
This coincides with the Richter Substitution principle, one of the six principles of the design pattern, which states that all references to base classes (abstract classes or interfaces) must be able to transparently use objects from their subclasses. That is, when you follow this principle, you must consider whether you care about a “flying car” entity or a “flying” behavior and use that as a base class to determine what subclass objects are acceptable to the program.
At the same time, the “interface isolation principle” instructs us that the dependence of one class on another should be based on the smallest interface. Compared with abstract FlyCar, interface Aircraft can minimize exposed interfaces and hide details, which is more in line with this principle.
So object orientation is just a guide to programming ideas, not rules. There is no absolute limit to the use of abstract classes or interfaces in real development, but it depends on your business scenario and architectural design.
5. To summarize
Ok, so that’s the end of this summary of interfaces and abstract classes. Do you understand them thoroughly? See you next time