In the previous section we introduced the basic concepts of inheritance and polymorphism, the basic concept is relatively simple, the subclass inherits the parent class, automatically owns the parent class's properties and behavior, and can extend the properties and behavior, and can override the parent class's methods to modify the behavior.
But there are some details about the inheritance and polymorphism concepts, which are discussed in this section, specifically:
- Construction method
- Duplicate names and static bindings
- Overloading and overriding
- Parent-Child type conversions
- Inherited access rights (protected)
- Visibility overrides
- Prevent inheritance (final)
Let's explain it one by one.
Construction method
Super
As we said in the previous section, subclasses can pass super (...) Call the constructor method of the parent class if the subclass does not pass super (...). Called, the default constructor method of the parent class is automatically mobilized, and if the parent class does not have a default constructor method? As shown in the following example:
Public class Base { private String member; Public Base (String member) { this. member = member; }}
This class has only one constructor with parameters and no default constructor method. At this time, any of its subclasses must be in the constructor method through Super (...). Call base with a parameter construction method , as shown below, otherwise Java will prompt a compilation error.
Public class extends Base { public child (String member) { Super(member); }}
Constructor method call override method
If you call a method that can be overridden in the parent class construction method, you may experience unexpected results , let's take a look at an example:
This is the base class code:
Public class Base { public Base () { test (); } Public void Test () { }}
The constructor method called Test (). This is the subclass code:
Public class extends Base { privateint a = 123; Public Child () { } publicvoid Test () { System.out.println (a); }}
The subclass has an instance variable a, an initial assignment of 123, overrides the test method, and outputs the value of a. Look at the code used:
Public Static void Main (string[] args) { new Child (); C.test ();}
The output is:
0123
The first output is 0, and the second time is 123. First act what is 0? The first output is output in the new process, in the new process, the first is to initialize the parent class, the parent class constructs the method call Test (), the Test quilt class overrides, the subclass's test () method is called, the subclass method accesses the child class instance variable a, This time the assignment and construction methods of the instance variables of the subclass have not been executed, so the output is its default value of 0.
In this way, calling a method that can be overridden in a parent class construction method is a bad practice that is confusing and should only call private methods.
Duplicate names and static bindings
As we said in the previous section, subclasses can override the parent class's non-private methods, and when invoked, dynamically bind and execute the subclasses ' methods. What about instance variables, static methods, and static variables? Do they have names? If the name is the same, which one is visited?
The same name is possible, there are actually two variables or methods after the name of the duplicate. for private variables and methods, they can only be accessed within the class, access is always the current class, that is, in the subclass, access to the child class, in the parent class, access to the parent class, they just happen to name the same, there is no relationship.
However, for public variables and methods, it is to see how to access it, within the class is access to the current class, but subclasses can pass super. Explicitly specify access to the parent class. Outside of the class, you want to see the static type of the access variable, the static type is the parent class, the variables and methods of the parent class are accessed, and the static type is a subclass, then the variables and methods of the child class are accessed. let's look at an example:
This is the base class code:
Public class Base { publicstatic String s = "Static_base"; Public String m = "base"; Public Static void statictest () { System.out.println ("base static:" +s);} }
A public static variable s, a public instance variable m, and a static method statictest are defined.
This is the subclass code:
Public class extends Base { publicstatic String s = "Child_base"; Public String m = "Child"; Public Static void statictest () { System.out.println ("Child static:" +s);} }
Subclasses define variables and methods that have the same name as the parent class. for a subclass object, it has two variables and methods, when accessed within the subclass, the subclass is accessed, or the subclass variables and methods hide the corresponding variables and methods of the parent class, and look at the externally accessed code:
Public Static void Main (string[] args) { new Child (); = C; System.out.println (B.S); System.out.println (B.M); B.statictest (); System.out.println (C.S); System.out.println (C.M); C.statictest ();}
The above code creates a subclass object, assigns the object to the subclass reference variable C and the parent class reference variable B, and then references the variables and methods by B and C, respectively. It is necessary to note that static and static methods are generally accessed directly through the class name, but can also be accessed through the object of the class. The program output is:
When accessed through B (static type base), access to the variables and methods of base, when accessed through C (static type child), access to the variables and methods of child, which is called static binding , that is, access to the static type bound to the variable, Static bindings are determined during the program compilation phase, while dynamic bindings wait until the program runs. instance variables, static variables, static methods, private methods, are all statically bound .
Overloading and overriding
Overloading refers to methods where the method name is the same but the parameter signature is different (the number of arguments or the type or order), overriding refers to a subclass that overrides the same parameter signature of the parent class. There may be multiple matching methods for a function call, and sometimes choosing one is not so obvious, let's look at an example:
Here's the base class code:
Public class Base { publicint sum (intint b) { System.out.println ( "Base_int_int"); return A +B; }}
It defines the method sum, and the following is the subclass code:
Public class extends Base { publiclong sum (longlong b) { System.out.println ( "Child_long_long"); return A +B; }}
Here's the code for the call:
Public Static void Main (string[] args) { new Child (); int a = 2; int b = 3; C.sum (A, b);}
What is the sum method of this call? Each sum method is compatible, and the int type can be automatically transformed to long, which is called when there is only one method. But now there are multiple methods available, the sum method parameter type of the subclass is not exactly matched but is compatible, and the parent class's sum method parameter type is exactly matched. The program output is:
Base_int_int
A method that exactly matches the parent class type is called. What if the parent code is changed to the following?
Public class Base { publiclong sum (intlong b) { System.out.println ( "Base_int_long"); return A +B; }}
The parent class method type does not exactly match. The program output is:
Base_int_long
The method that is called by the parent class. The type of the two methods of the parent and subclass do not exactly match, why is the parent class called? Because the parent class is more matched. now change the class code to:
Public class extends Base { publiclong sum (intlong b) { System.out.println ( "Child_int_long"); return A +B; }}
The program output becomes:
Child_int_long
Finally, the method of the subclass is called. As you can see, when there are multiple duplicate functions, in deciding which function to invoke, the first is to match the parameter type, in other words, to look for the most matching in all overloaded versions before looking at the dynamic type of the variable and dynamically binding.
Parent-Child type conversions
As we said before, objects of subtypes can be assigned to reference variables of the parent type, which is called upward transformation, and can a variable of the parent type be assigned to a variable of the subtype? Or can it be a downward transition? you can enforce type conversions on the syntax, but you may not necessarily be able to convert successfully. Let's take an example from the above example:
New= (child) b;
Child C = (child) b is to cast the type of variable B to child and assign a value of C, which is fine because the dynamic type of B is child, but the following code is not possible:
New= (child) b;
Syntax Java does not error, but the runtime throws an error, and the error is a type conversion exception.
A variable of a parent class can be converted to a variable of a subclass, depending on whether the dynamic type of the parent class variable (that is, the object type being referenced) is a subclass of this subclass or subclass of the child class.
Given a variable of a parent class, is it possible to know whether it is an object of a subclass or not, so that it can be converted safely? The answer is yes, by the instanceof keyword, look at the following code:
Public Boolean Cancast (Base b) { returninstanceof child ;}
This function returns whether the base type variable can be converted to the child type, instanceof is preceded by avariable, followed by a class, and the return value is a Boolean value that indicates that the object referenced by the variable is not an object of that class or its subclasses.
Protected
Variables and functions have public/private modifiers, public means that they can be accessed externally, private means they can only be used internally, and there is a modifier protected the middle of the visibility, which means that although it cannot be accessed externally, But can be accessed by the quilt class. In addition, in Java, protected also indicates that it can be accessed by other classes in the same package, regardless of whether the other class is a subclass of that class, and then we discuss the package in the next section.
Let's look at an example, which is the base class code:
public class Base { protected int Currentstep; protected void Step1 () {} protected void
Step2 () {}
public
void
Action () {
; Step1 ();
this . Currentstep = 2
The action () indicates the behavior provided externally, there are two steps inside Step1 () and Step2 (), using the CURRENTSTEP variable to indicate which step is currently in progress, Step1, Step2, and currentstep are protected, Subclasses generally do not rewrite action, but only Step1 and Step2, while subclasses can access the Currentstep directly to see which step to take. The code for the subclass is:
Public class extends Base { protectedvoid Step1 () { System.out.println ("Child Step" + This . Currentstep); } protected void Step2 () { System.out.println ("Child Step" +this. currentstep); }
The code to use child is:
Public Static void Main (string[] args) { new Child (); C.action ();}
The output is:
Child Step 1child Step 2
The base class defines the method action that represents the external behavior, and defines the two steps step1 and Step2, which can be overridden by the quilt class, and the variable currentstep that the quilt class looks at, and the subclass modifies the external behavior by overriding the protected method Step1 and Step2.
This idea and design is called the template method in the design pattern, the action method is a template method, it defines the implementation template, and the concrete implementation is provided by subclasses. template methods are widely used in many frameworks, which is a common scenario for using protected. we do not introduce the contents of more design patterns.
Visibility overrides
When overriding a method, the visibility of the method is not generally modified. But let's just make it clear that when overridden, a subclass method cannot degrade the visibility of a parent class method, or it means that, if the parent class is public, the subclass must also be public, and if the parent class is protected, the subclass can be protected, It can also be public, where subclasses can upgrade the visibility of a parent class method but not degrade it. As shown below:
The base class code is:
Public class Base { protectedvoid Protect () { } public void Open () { }}
The sub-class code is:
public class child extends Base { // // private void protect { // } // The following is not allowed, there will be a compile error // protected void Open () { // } public protect () {}}
Why is it so stipulated? Inheritance reflects the "is-a" relationship, that is, the subclass object also belongs to the parent class, the subclass must support all the external behavior of the parent class, reduce the visibility of the child class to the external behavior, thereby destroying the "is-a" relationship, but the subclass can increase the behavior of the parent class, so the promotion of visibility is not a problem.
Prevent inheritance (final)
In the last section we mentioned that inheritance is a double-edged sword, specific reasons for our subsequent chapters, the impact is that sometimes we do not want the parent method quilt class rewrite, sometimes even do not want to inherit the class, the way to implement this is the final keyword. We mentioned before that final can modify variables, which is another use of final.
A Java class that can be inherited by default, but cannot be inherited after the final keyword is added, as follows:
Public Final class Base { //...}
A non-final class in which the public/protected instance method can be overridden by default, but cannot be overridden after the final keyword is added, as follows:
Public class Base { publicfinalvoid Test () { System.out.println ("cannot be overridden" ); }}
Summary
In this section we discuss some of the details of the introduction of the Java inheritance concept, some of the details may be encountered less often, but we still need to have a good understanding of them, including some of the details of the construction methods, variables and methods of the same name, parent-child type conversion, protected, visibility rewrite, final and so on.
But there are some important things that we don't discuss, such as the specific process of creating a subclass object? How is dynamic binding implemented? Let's explore the fundamentals of inheritance implementations in the next section.
----------------
To be continued, check out the latest articles, please pay attention to the public number "old Horse Programming" (Scan the QR code below), from the introduction to advanced, in layman's words, Lao Ma and you explore the nature of Java programming and computer technology. Original article, All rights reserved.
Logic of the computer program (16)-Details of the inheritance