Thinking in Java inner classes
Introduction
Each JVM has two mechanisms: one is to load a class (class or interface) with the appropriate name, called the class loading subsystem; the other one is responsible for executing commands contained in loaded classes or interfaces, called the running engine. Each JVM also includes five parts: Method Area, heap, java stack, program counter, and local method stack. The architecture of these parts is composed of the class loader and running engine mechanism:
JVM:
Abstract specifications;
A specific implementation
A running Virtual Machine instance
Loader: Start the class loader and customize the loader (inherited from Java. Lang. classloader)
The parsed internal information is put into the method area, the object is put into the heap, a new thread has its own java stack to put intermediate data, PC counters.
In-depth interface and abstract class
Java does not have multiple inheritance, which means that a class can only inherit one parent class, so it is absolutely necessary to use inheritance.
Therefore, methods that indicate the same behavior should be declared as an interface and implemented using different implementation classes.
Disadvantage: all methods in the implementation Declaration must be displayed for each implementation class. Even in some cases, these methods represent the unchanged functional parts, and all classes have identical implementations, leading to redundant code.
Public String GETID (){
Return ID;
}
}
Public void save (){
Fileutil futil = new fileutil ();
Futil.writetofile(“emp.txt ", this, tostring, true, true );
}
Public abstract string computecompensation ();
}
Employees with different titles have different salary calculation methods. Such an operation is implemented in multiple ways.
Public class consultant extends employee {
Public String computecompensation (){
Return ("Consultant salary ");
}
Public consultant (string empname, string empid ){
Super (empname, empid );
}
}
Pulbic class salesrep exends employee {
Public String computecompensation (){
Retrun ("salesrep salary ");
}
Public salesrep (string empname, string empid ){
Super (empname, empid );
}
}
Implemented using abstract classes
Implemented Using Interfaces
If the interface is used for implementation, all the implementation classes should be provided
Save, GETID, getname, and other methods. This leads to redundant code.
Differences between interfaces and abstract classes at the design level
"A class can only continue with one abstract class at a time, but it can implement several interfaces ".
The term "continue-class, implementation-Interface" is the term "continue". The abstract parent class and its subclass reflect a "continue" relationship, to make the "continue" relationship reasonable, there should be a "is-a" relationship between the abstract parent class and the Child class, that is, the parent class and the Child class should be essentially the same concept.
For interfaces, the interface is "implemented" and does not require that the interface implementation classes and interface definitions be consistent in concept, because we all know that, an interface only defines the framework of a set of methods. Its essence is a set of behavioral features and its specifications. A class implements an interface and only implements the specifications defined by the interface. The class implementing the interface does not "Belong" to "the interface! At this time, it should be said that the relationship between the interface and the subclass that implements the interface is a kind of "like-a" relationship.
In addition, a class can implement multiple interfaces. In this case, the class that implements multiple interfaces shows "like-a, like-B, like-C. Abstract classes cannot do this in Java. Suppose that even if we can do this, if a class is-a, is-B, is-C, this is not consistent with our understanding of the world. When we look at things, we are used to assigning things to one class, but at the same time we can have other class features.
Consider this example. Suppose we are developing mobile phone software for a manufacturer. There is an abstract concept about the mobile phone in the problem field. The mobile phone has some actions, such as starting and shutting down the mobile phone, in this case, you can define a type that represents the abstract concept through an interface or abstract class, as shown below:
Define the mobile phone using the interface:
Interface mobile_phone {
Void pen ();
Void close ();
}
Define mobile phones using abstract classes:
Abstract class mobile_phone {
Abstract void open ();
Abstract void close ();
}
The specific mobile phone type can be defined in the abstract class or the interface implementation method. It seems that there is no big difference between using interfaces and abstract classes.
Assume that mobile phones are required to be integrated with credit card functions. How should we design the class structure for this example?
Some basic functions of credit cards include electronic wallet and consumption. These functions are different from the startup and shutdown functions of mobile phones.Ciple) principles should be defined in the abstract representation representing the two concepts respectively. The abstract concept of credit card may be defined in the following two situations:
Interface creditcard {
Void e_wallet (); // E-Wallet
Void consume (); // consume
}
Or
Abstract class creditcard {
Abstract void e_wallet ();
Abstract void consume ();
}
At this time, there are four possible combinations of the two concepts of mobile phone and bank card, as shown in the following table:
Mobile phone
Credit Card
Solution
Mobile phone is defined as abstract class
Credit card is defined as abstract class
Solution B
Mobile phone is defined as abstract class
Credit card is defined as interface
Solution C
Mobile phone is defined as interface
Credit card is defined as abstract class
Solution d
Mobile phone is defined as interface
Credit card is defined as interface
Solution A can be ruled out immediately because JAVA does not support more than one continuation. Mobile phones must be integrated with credit card implementation classes, which cannot be used to continue these two abstract classes at the same time. Here we can see that abstract classes are inconvenient to Expand functions by combining concepts.
Study solution C. As described in this article, the relationship between the classes that implement these two concepts and the two concepts is: "like" mobile phone, "is" credit card. Obviously, this is not consistent with our understanding of the problem field. Because "mobile phones with credit card functions" are essentially mobile phones and credit card functions at the same time. Therefore, this solution is unreasonable. Unless we are writing software for credit card manufacturers, they want to add mobile phone features.
Moreover, if mobile phone extension functions, such as electronic maps, navigators, and so on, define the extended function concept as an abstract class like "Credit Card", because of Java's single-continue mechanism, this cannot be achieved. Like Solution A, it is not appropriate to define the concept of extended functionality as an abstract class.
Solution B should be the most reasonable design at present. The concept is "is mobile phone, like credit card ". If there is an extended function, you can define it as an interface and become "is mobile phone, like credit card like electronic map ---", so as to correctly reflect the problem domain we are facing.
Is Solution d not feasible?
Compared with solution C, the design of Solution d does not reflect that "Mobile Phone" is the essential subject of the problem field, and enables people to "whether we are engaged in mobile phones, credit cards, or other things?" This question. This shortcoming is unquestionable. On the other hand, the concept of "Mobile Phone" is defined as an interface, which may facilitate the use of other components in the future when the software scale is expanded. For example, if the manufacturer has another concept of "remote control", we need to design the function of the mobile phone. At this time, "Mobile Phone" is convenient if it is an interface, just implements. Therefore, Solution d sacrifices the clarity of the concept and achieves scalability.
The conclusion here is that, if we only define a set of behavior frameworks, abstract classes can be used to define the essential abstract concepts in the problem field, and interfaces can be used to define the abstract concepts of extended functions.
It cannot be said that this conclusion summarizes all the differences between abstract classes and interfaces. This is only a small part of the conclusion. Let's take another example to illustrate their differences.
In this example, "Mobile Phone" and "Credit Card" are just a set of abstract methods, that is, they only contain the fact that the behavior framework is not implemented, at this time, defining it as an abstract class or interface has its own principle. If the concept already contains an implementation, the concept should be defined as an abstract class.
For example, an abstract class of "a series printer" defines different types of printers. The layout of the headers and footer of the series of printers is the same, but the layout of the printed page is complicated, different types of printers have different printing methods. You can design them as follows:
Solution 1: print the complete page according to the natural logic of the printer. The body abstraction method is part of the printer concept and is designed as an abstract class:
Abstract class a_seriesprinter {
Abstract protected void printbody ();
Public void outreport (){
Printheader ();
Printbody ();
Printfooter ();
}
Protected void draw (stringstr) {/implemented code /}
Protected void printheader () {draw ("head");/implemented code /}
Protected void printfooter () {draw ("footer");/implemented code /}
}
Continue the code of the abstract class:
Class xxprinter extends a_seriesprinter {
Protected void printbody () {/implemented code} // must be implemented?
}
Classyyprinter extends a_seriesprinter {
Protected void printbody () {/implemented code /}
}
Code used:
Xxprinterxx = new xxprinter ();
XX. outreport ();
Yyprinteryy = new yyprinter ();
YY. outreport ();
Obviously, this solution is simple and clear.
Solution 2: To achieve scalability, obtain the body abstraction method as an interface. The Code is as follows:
Abstract class a_seriesprinter {// do you still use abstract?
Protected void draw (stringstr) {/implemented code /}
Protected void printheader () {draw ("head");/implemented code /}
Protected void printfooter () {draw ("footer");/implemented code /}
}
Interface body {
Void printbody (); // the concept of an additional body interface
}
Here we will solve a problem first. If printer removes the printbody abstract method, it will all be implemented. Should it be defined as a common class?
The answer is no. The meaning of designing an abstract concept as an abstract class is not because it contains an abstract method, but because the concept he represents should not be instantiated, even if all the methods in it are implemented, the code that you want the subclass to continue. In the above example, there should be no instance for the "A series printer" concept, and there should be a printer of a specific model. Therefore, even if all the methods are implemented, the_seriesprinter in solution 2 is better defined as an abstract class.
Okay. Continue to check the code for continuing the class and implementing the interface:
Class xxprinter extends a_seriesprinter implement body {
Public void printbody () {;/implemented code /}
Public void outreport () {// outreport () is forced to be moved to the implementation class
Printheader ();
Printbody ();
Printfooter ();
}
}
Class yyprinter extends a_seriesprinter implement sbody {
Public void printbody () {;/implemented code /}
Public void outreport () {// outreport () is forced to be moved to the implementation class
Printheader ();
Printbody ();
Printfooter ();
}
}
Code used:
Xxprinter xx = new xxprinter ();
XX. outreport ();
Yyprinter YY = new yyprinter ();
YY. outreport ();
This will seem strange and complicated: Class xxprinter extends printer implements body? Is the print body an additional function of the printer? The concept of a body interface is added for no reason. In addition, outreport () is forced to move to various implementation classes, and the code becomes longer and more complex.
Therefore, abstract classes are the best choice. Unless there are business requirements, the print of the body should be separated from the printer. Set it to another concept. This makes it an interface possible, but I would like to remind you that the Code will become complicated.
Trace the source of the problem because the abstract method printbody () is too closely integrated with the printer concept and is an indispensable part of the printer function. The syntax flexibility of the greedy image interface, blindly pursuing scalability and openness, and modeling regardless of the understanding of the problem field, as long as the behavior framework contained in a certain concept is separated to form an interface, there will be a series of coding and understanding troubles, but it increases the complexity of the code, so you have to suffer.
However, even when using abstract classes, do not ignore the principle of defining behavior models through interfaces. If behaviors are defined by abstract classes, they often lead to overly complex inheritance relationships. Defining behaviors through interfaces can effectively separate behavior and implementation and facilitate code maintenance and modification.
For example, if I extend the_seriesprinter class and add a log information after printing, such as the vidoutlog () method or something, then I should not define it as an abstract method of the_seriesprinter class, but a log interface. Because the concept of "log" does not belong to the proprietary category of printers. In this way, other modules can easily use this log interface when using log operation specifications.
Therefore, the key is whether the problem domain can be well understood and analyzed based on business requirements. If you do not do this well, you cannot establish a reasonable model.
Summary:
1. The interface can be transformed to multiple basic types.
2. The interface prevents the client programmer from generating objects. Make sure that this is only an interface, abstract class, and no entity.
3. When designing the base class of the basic class without any function definition or member variables, consider interface first. (If function definition or member variables must be included, use abstract class instead)
4. To eliminate the same Implementation of unchanged functions, avoid code redundancy and apply abstract classes
5. In the implementation of polymorphism, the relationship between is-a and like-
Is-A is a completely replaced base class method (overring overwriting), overload (overloader) function, the relationship between an interface and a subclass that implements an interface is a "like-a" polymorphism.