In the Java language, abstract class and interface are two mechanisms that support abstract class definition. It is precisely because of the existence of these two mechanisms that Java is given powerful object-oriented capabilities. There are great similarities between abstract class and interface in terms of support for abstract class definition, and they can even be replaced with each other. Therefore, many developers seem to be more casual about the choice of abstract class and interface when defining abstract classes. In fact, there is still a big difference between the two. The choice of them even reflects the understanding of the nature of the problem domain and whether the understanding of the design intention is correct and reasonable. This article will analyze the differences between them and try to provide developers with a basis for choosing between the two.
Understand abstract classes
Abstract class and interface are both used to define abstract classes in the Java language (the abstract class in this article is not translated from abstract class, it represents an abstract body, and abstract class is used to define abstract classes in the Java language) A method, please pay attention to the distinction), so what is an abstract class, and what benefits can using abstract classes bring us?
In the object-oriented concept, we know that all objects are represented by classes, but the reverse is not true. Not all classes are used to describe objects. If a class does not contain enough information to describe a specific object, such a class is an abstract class. Abstract classes are often used to represent abstract concepts that we derive from analysis and design of problem areas. They are abstractions of a series of specific concepts that look different but are essentially the same. For example: If we develop a graphics editing software, we will find that there are some specific concepts such as circles and triangles in the problem domain. They are different, but they all belong to the concept of shape. The concept of shape is different in the problem domain. If it exists, it is an abstract concept. It is precisely because abstract concepts do not have corresponding concrete concepts in the problem domain, so the abstract classes used to represent abstract concepts cannot be instantiated.
In the object-oriented field, abstract classes are mainly used for type hiding. We can construct an abstract description of a fixed set of behaviors, but this set of behaviors can have any number of possible concrete implementations. This abstract description is the abstract class, and this set of any possible concrete implementations is represented by all possible derived classes. Modules can operate on an abstract body. Because a module relies on a fixed abstraction, it cannot be modified; at the same time, the behavior of this module can also be extended by deriving from this abstraction. Readers who are familiar with OCP must know that in order to realize OCP (Open-Closed Principle), one of the core principles of object-oriented design, abstract classes are the key.
Looking at abstract class and interface from the grammatical definition level
At the grammatical level, the Java language provides different definition methods for abstract class and interface. The following is an example of defining an abstract class named Demo to illustrate this difference.
The way to define the Demo abstract class using abstract class is as follows:
abstract class Demo{
abstract void method1();
abstract void method2();
…
}
The way to define the Demo abstract class using interface is as follows:
interface Demo{
void method1();
void method2();
…
}
In the abstract class method, Demo can have its own data members or non-abstract member methods. In the interface method, Demo can only have static data members that cannot be modified (that is, it must be static final). , but data members are generally not defined in the interface), and all member methods are abstract. In a sense, interface is a special form of abstract class.
From a programming perspective, both abstract class and interface can be used to implement the idea of "design by contract". However, there are still some differences in specific usage.
First of all, abstract class represents an inheritance relationship in the Java language, and a class can only use the inheritance relationship once (because Java does not support multiple inheritance - transfer note). However, a class can implement multiple interfaces. Perhaps this is a compromise consideration by the designers of the Java language when considering Java's support for multiple inheritance.
Secondly, in the definition of abstract class, we can assign the default behavior of the method. But in the definition of interface, methods cannot have default behavior. In order to circumvent this restriction, delegates must be used, but this will add some complexity and sometimes cause a lot of trouble.
There is another serious problem in not being able to define default behavior in an abstract class, which is that it may cause maintenance trouble. Because if you later want to modify the interface of the class (usually represented by abstract class or interface) to adapt to new situations (for example, adding new methods or adding new parameters to already used methods), it will be very troublesome. It may take a lot of time (especially if there are many derived classes). But if the interface is implemented through an abstract class, then you may only need to modify the default behavior defined in the abstract class.
Similarly, if the default behavior cannot be defined in an abstract class, the same method implementation will appear in every derived class of the abstract class, violating the "one rule, one place" principle, resulting in code duplication, which is also detrimental to the future. maintenance. Therefore, be very careful when choosing between abstract class and interface.
Looking at abstract class and interface from the design concept level
The above mainly discusses the difference between abstract class and interface from the perspective of grammatical definition and programming. The differences at these levels are relatively low-level and non-essential. This section will analyze the difference between abstract class and interface from another level: the design concepts reflected in the two. The author believes that only by analyzing from this level can we understand the essence of the two concepts.
As mentioned earlier, abstract class embodies an inheritance relationship in the Java language. In order to make the inheritance relationship reasonable, there must be an "is-a" relationship between the parent class and the derived class, that is, the parent class and the derived class have the same concept. Essentially it should be the same. This is not the case for interfaces. The implementer of the interface and the interface definition are not required to be conceptually consistent, but only implement the contract defined by the interface. In order to make the discussion easier to understand, a simple example will be illustrated below.
Consider such an example. Suppose there is an abstract concept about Door in our problem domain. The Door has two actions: open and close. At this time, we can define a type that represents the abstract concept through abstract class or interface. The definition methods are as follows:
Use abstract class to define Door:
abstract class Door{
abstract void open();
abstract void close();
}
Define Door using interface method:
interface Door{
void open();
void close();
}
Other specific Door types can extend the Door defined using the abstract class method or implement the Door defined using the interface method. It seems that there is no big difference between using abstract class and interface.
If Door is now required to have an alarm function. How should we design the class structure for this example (in this example, it is mainly to show the difference in design concepts between abstract class and interface, and other irrelevant issues have been simplified or ignored)? Possible solutions are listed below and these different options are analyzed from a design concept level.
Solution one:
Simply add an alarm method to the definition of Door, as follows:
abstract class Door{
abstract void open();
abstract void close();
abstract void alarm();
}
or
interface Door{
void open();
void close();
void alarm();
}
Then the AlarmDoor with alarm function is defined as follows:
class AlarmDoor extends Door{
void open(){…}
void close(){…}
void alarm(){…}
}
or
class AlarmDoor implements Door{
void open(){…}
void close(){…}
void alarm(){…}
}
This method violates ISP (Interface Segregation Principle), a core principle in object-oriented design. In the definition of Door, the inherent behavior method of the Door concept itself is mixed with the behavior method of another concept "alarm". One problem caused by this is that modules that only rely on the concept of Door will change due to changes in the concept of "alarm" (for example, modifying the parameters of the alarm method), and vice versa.
Solution two:
Since open, close and alarm belong to two different concepts, according to the ISP principle, they should be defined in abstract classes representing these two concepts. The definition methods are: both concepts are defined using abstract class method; both concepts are defined using interface method; one concept is defined using abstract class method, and the other concept is defined using interface method.
Obviously, since the Java language does not support multiple inheritance, it is not feasible to define both concepts using abstract class. The latter two methods are both feasible, but their choice reflects the understanding of the essence of the concept in the problem domain and whether the reflection of the design intention is correct and reasonable. Let’s analyze and explain one by one.
If both concepts are defined using the interface method, then it reflects two problems: 1. We may not understand the problem domain clearly. Is AlarmDoor essentially a door or an alarm? 2. If there is no problem with our understanding of the problem domain, for example: through analysis of the problem domain, we find that AlarmDoor is conceptually consistent with Door, then we will not be able to correctly reveal our design intent when implementing it, because The definitions of these two concepts (both defined using the interface method) do not reflect the above meaning.
If our understanding of the problem domain is: AlarmDoor is conceptually essentially a Door, and it also has the function of alarming. How should we design and implement it to clearly reflect our meaning? As mentioned before, abstract class represents an inheritance relationship in the Java language, and the inheritance relationship is essentially an "is-a" relationship. So for the concept of Door, we should use the abstract class method to define it. In addition, AlarmDoor has an alarm function, which means that it can complete the behavior defined in the alarm concept, so the alarm concept can be defined through the interface. As shown below:
abstract class Door{
abstract void open();
abstract void close();
}
interfaceAlarm{
void alarm();
}
class Alarm Door extends Door implements Alarm{
void open(){…}
void close(){…}
void alarm(){…}
}
This implementation method can basically clearly reflect our understanding of the problem domain and correctly reveal our design intentions. In fact, abstract class represents the "is-a" relationship, and interface represents the "like-a" relationship. You can use it as a basis when choosing. Of course, this is based on the understanding of the problem domain. For example: If we If AlarmDoor is essentially an alarm in concept and has the function of a Door, then the above definition must be reversed.
summary
1.Abstract class represents an inheritance relationship in the Java language, and a class can only use the inheritance relationship once. However, a class can implement multiple interfaces.
2. In abstract class, you can have your own data members, and you can also have non-abstarct member methods, but in interface, you can only have static data members that cannot be modified (that is, they must be static final, but in interface Data members are generally not defined), and all member methods are abstract.
3.Abstract class and interface reflect different design concepts. In fact, abstract class represents the "is-a" relationship, and interface represents the "like-a" relationship.
4. Classes that implement abstract classes and interfaces must implement all methods in them. Abstract classes can have non-abstract methods. There cannot be implementation methods in the interface.
5. The variables defined in the interface are public static final by default, and their initial value must be given, so they cannot be redefined in the implementation class, nor can their values be changed.
6. Variables in abstract classes are friendly by default, and their values can be redefined in subclasses or reassigned.
7. The methods in the interface are of public and abstract type by default.
in conclusion
Abstract class and interface are two ways of defining abstract classes in the Java language, and they are very similar. However, their selection often reflects the understanding of the essence of the concept in the problem domain and whether the reflection of the design intention is correct and reasonable, because they express different relationships between concepts (although they can all achieve the required functions). This is actually a kind of idiomatic usage of language. I hope readers can understand it carefully.