Select an interface or an abstract class

xiaoxiao2021-03-06  56

Author: Yuliang Song This article taken from: open systems world - SEOUL March 12, 2003

Many people have such questions: Why do some places must use interfaces instead of abstract classes, while others must use abstract classes rather than interface? Or, when considering the generalization of Java classes, many people will hesitate between interfaces and abstract classes, and even choose one.

In fact, the choice of interfaces and abstract classes is not as you want. It is important to understand the principle of interface and abstract classes, and there are two concepts that are important: the behavior of the object and the implementation of the object. If an entity can have a variety of implementations, such a goal should be achieved when designing entity behavior: When using entities, there is no need to detail the implementation of entity behavior. That is to say, it is to be separated from the behavior of the object and the implementation of the object. Since Java's interface and abstract classes can define methods that do not provide specific implementation, when the target's behavior and object implementation, should I use an image or use abstract class?

Establish behavior model by abstract class

In the selection of interfaces and abstract classes, you must follow such a principle: behavioral model should always pass the interface instead of an abstract class definition. To illustrate the reasons, you will try to create behavioral models through abstract classes to see what problems will occur.

Suppose you want to design a software for the sales department, this software contains a "motor) entity. Obviously, the roof of the engine cannot be described in detail in the engine object, and some features important to current software can be described. As for which features of the engine are important, it is necessary to communicate with the user (sales department) to determine.

People in the sales department require every engine with a parameter called horsepower. For them, this is the only parameter worthy of concern. Based on this judgment, the behavior of the engine can be defined as the following behavior.

Behavior 1: Query the horsepower of the engine, the engine will return an integer representing horsepower.

Although it is still unclear how the engine gets the parameters of the horsepower, it can affirm the engine must support this behavior, and this is the only behavior characteristic of all engines. This behavior feature can be defined by interface or an abstract class definition. To illustrate the possible problems that can be arbitrarily defined, the behavior model of the engine is established by the abstract class, and the behavior 1 is described with the Java method, the code is as follows:

Public abstract motor {

Abstract public int gethorsepower ();

}

A variety of specific implementations are constructed on the basis of the Motor abstraction, such as a Type A engine, a B type engine, etc., plus the other portions of the system, and finally obtain 1.0 version of software and delivered. For a while, I have to design a version 2.0 version. In the process of evaluating version 2.0 software, a small part of the engine is found to be battery-driven, while the battery needs a certain charging time. People from the sales department want to be able to view the charging time through the computer. Define a new behavior based on this request, as shown in Figure 1.

Behavior 2: Query the charging time of the electric drive engine, the engine will return an integer representing the charging time.

With the Java method to describe this behavior, the code is as follows:

Public Abstract BatterypoweredMotor Extends Motor {

Abstract public int GetTimetorecharge ();

}

In the software of the sales department, the electric drive engine is also implemented in the form of a class, but these classes are derived from BatteryPoweredMotor instead of Motor. After these changes are added to version 2.0 software, the sales department is very satisfied. As the business continues to develop, the engine driver has appeared soon. The sales department requires light-driven engines that require a certain light energy to operate, and the light can be measured in Lumen. This information is important to the customer, because in rainy or cloudy weather, certain optical drive engines may not work. The sales department requires the addition of support for optical drive engines to define a new behavior. Behavior 3: Querying the light-driven engine can run normally to the minimum lottery, the engine returns an integer.

Refine an abstract class and convert behavior 3 into a Java method, the code is as follows:

Public Abstract SolarPoweredMotor Extends Motor {

Abstract public int getlumenStooperate ();

}

As shown in Figure 1, SolarPoweredMotor and BatteryPoweredMotor are derived from the Motor abstraction class. In the entire software, 90% of the code treats all the engines in the same way. Occasionally, check the engine is optical drive or electric drive, using the instanceof implementation, the code is as follows:

IF (InstanceOf SolarPoweredMotor) {...}

IF (InstanceOf BatteryPoweredMotor) {...}

No matter which engine, the parameters of horsepower are important, so in all derived abstract classes (SolarPoweredMotor and BatteryPoweredMotor), the gethorsEPower () method is valid.

Now there is a new engine in the sales department, which is a dual drive engine that exists both electrically driven and light. The behavior of optical drive and electrical drive itself does not change, but new engines support two behaviors. When considering how to define a new type of photoelectric drive engine, the difference in interfaces and abstraction classes starts to appear. The new goal is to change the code as little as possible under the premise of increasing the new engine. Because of the optical drive engine, the electrical drive engine has a comprehensive test, there is no known bug. In order to increase photoelectric drive engines, define a new SolarbatteryPowred abstraction class. If SolarBatterypowered is derived from the Motor abstraction class, SolarBatterypowred will not support instanceOf operations for optical drive engines and electrical drive engines. That is, if you query a photoelectric drive engine is optical drive, or the electrically driven, the resulting answer is: all.

If you let SolarbatteryPowred from SolarPoweredMotor (or BatteryPoweredMotor) abstract class derived, similar questions will also appear, SolarBatteryPowred will not support instanceOf operations for BatteryPoweredMotor (or SolarPoweredMotor). From a behavior, photoelectric drives must be derived from two abstractions, but the Java language does not allow multiple inheritance. This problem occurs, the fundamental reason is that the use of abstract classes not only means defining specific behaviors, but also means that the implementation is defined. That is, it should be defined how the engine has a model of behavior, not just a declaration engine has a certain behavior.

Establish behavior model through interface

If you use an interface to create a behavior model, you can avoid implicitting implementation mode. For example, the previous behavior is defined as follows.

Behavior 1:

Public interface motor () {public int gethorsepower ();

}

Behavior 2:

Public interface batterypoweredmotor extends motor () {

Public int gettimetorecharge ();

}

Behavior 3:

Public interface solarpoweredmotor extends motor {

Abstract public int getlumenStooperate ();

}

Now the photovoltaic engine can be described as:

Public DualPoweredMotor Implements SolarPoweredMotor, BatterypoweredMotor {}

DualPoweredMotor only inherits behavior definitions, not behavior, as shown in Figure 2.

The abstract class can still be used while using the interface, but the effect of the abstract class is to achieve behavior, not the definition behavior. As long as the class definition of the behavior is implemented, even if it changes the parent abstraction class, it does not have to change the way other code and interaction. Especially for public implementation code, abstract classes have its advantages. Abstract classes guarantee the hierarchical relationship to avoid code repeat. However, even if the abstract class is used, do not ignore the principle of defining behavioral models through interfaces. From a practical point of view, if the behavior is depends on an abstract class, it often leads to too complex inheritance relationships, and the behavior of the interface definition can be more effectively separated and implemented, which is convenient for code maintenance and modification.

转载请注明原文地址:https://www.9cbs.com/read-113391.html

New Post(0)