Basic concepts of inheritance and synthesis
Inheritance: A new class can be constructed based on an existing class. Inheriting existing classes can reuse methods and domains of these classes. On this basis, new methods and domains can be added to expand the functions of the class.
Synthesis: Creating the original object in a new class is called synthesis. This way you can reuse existing code without changing its form.
1. Inherited syntax
The keyword extends indicates that the new class is derived from an existing class. An existing class is called a parent class or a base class, and a new class is called a subclass or a derived class. For example:
class Student extends Person {}The class Student inherits Person. The Person class is called a parent class or base class, and the Student class is called a subclass or derived class.
2. Synthesis of Synthesis
Synthesis is relatively simple, which is to create an existing class in a class.
class Student { Dog dog;}Upward styling
1. Basic concepts
The role of inheritance lies in the reuse of code. Since inheritance means that all methods of the parent class can also be used in subclasses, messages sent to the parent class can also be sent to the derivative class. If there is an eat method in the Person class, then there will be this method in the Student class, which means that the Student object is also a type of Person.
class Person {public void eat() {System.out.println("eat");}static void show(Person p) {p.eat();}}public class Student extends Person{public static void main(String[] args) {Student s = new Student();Person.show(s);// ①}}【Operation results】:
eat
The show method defined in Person is used to receive Person handles, but at ① it receives a reference to the Student object. This is because the Student object is also a Person object. In the show method, the handle (reference to the object) passed in can be a Person object and a Person derived class object. This behavior of converting Student handles into Person handles becomes an upward pattern.
2. Why do you need to trace the shape?
Why do you want to deliberately ignore the object type that calls it when calling eat? If you make the show method simply get the Student handle, it seems more intuitive and easy to understand, but that will make every new class derived from the Person class implement its own show method:
class Value {private int count = 1;private Value(int count) {this.count = count;}public static final Value v1 = new Value(1), v2 = new Value(2), v3 = new Value(3);}class Person {public void eat(Value v) {System.out.println("Person.eat()");}}class Teacher extends Person {public void eat(Value v) {System.out.println("Teacher.eat()");}}class Student extends Person {public void eat(Value v) {System.out.println("Student.eat()");}}public class UpcastingDemo {public static void show(Student s) {s.eat(Value.v1);}public static void show(Teacher t) {t.eat(Value.v1);}public static void show(Person p) {p.eat(Value.v1);}public static void main(String[] args) {Student s = new Student();Teacher t = new Teacher();Person p = new Person();show(s);show(t);show(p);}}An obvious flaw in this approach is that it is necessary to define methods closely related to each Person class's derivative class, resulting in a lot of duplicate code. On the other hand, if you forget the overloading of the method, you will not report an error. The three show methods in the above example can be merged into one:
public static void show(Person p) { p.eat(Value.v1);} Dynamic binding
When performing show(s), the output result is Student.eat(). This is indeed the desired result, but it does not seem to be executed in the form we hoped. Let's take a look at the show method again:
public static void show(Person p) { p.eat(Value.v1);}It receives a Person handle. When performing show(s), how does it know that the Person handle points to a Student object instead of a Teacher object? The compiler has no way of knowing it, which involves the binding issue to be explained next.
1. Method call binding
Connecting a method and the same method body together is called binding. If binding is performed before running, it is called "early binding". In the above example, when there is only one Person handle, the compiler does not know which method to call. Java implements a method calling mechanism that can determine the type of an object during operation and then call the corresponding method. This binding based on the type of the object is called dynamic binding during operation. Unless a method is declared final, all methods in Java are dynamically bound.
Use a picture to represent the inheritance relationship of the upward shape:
In code, it is summarized as:
Shapes=newShape();
According to the inheritance relationship, it is legal to assign the created Circle object handle to a Shape, because Circle belongs to a Shape.
When one of the basic class methods is called:
Shapes=newShape();
At this time, Circle.draw() is called, which is due to dynamic binding.
class Person {void eat() {}void speak() {}}class Boy extends Person {void eat() {System.out.println("Boy.eat()");}void speak() {System.out.println("Boy.speak()");}}class Girl extends Person {void eat() {System.out.println("Girl.eat()");}}public class Persons {public static Person randPerson() {switch ((int)(Math.random() * 2)) {default: case 0: return new Boy();case 1: return new Girl();}}public static void main(String[] args) {Person[] p = new Person[4];for (int i = 0; i < p.length; i++) {p[i] = randPerson();// Randomly generate Boy or Girl}for (int i = 0; i < p.length; i++) {p[i].eat();}}}For all classes derived from Person, Person establishes a general interface, and all derived classes have two behaviors: eat and speak. The derived class overrides these definitions and redefines both behaviors. In the main class, randPerson randomly selects the handle of the Person object. **The appeal style occurs in the return statement. The **Return statement takes a Boy or Girl handle and returns it as a Person type. At this time, I don’t know what type it is, I only know it is a Person object handle. In the main method, call the randPerson method to fill in the Person object to the array, but do not know the specific situation. When the eat method of each element of the array is called, the function of dynamic binding is to execute the redefined method of the object.
However, dynamic binding is a prerequisite, and the binding method must exist in the base class, otherwise it will not be compiled and passed.
class Person {void eat() {System.out.println("Person.eat()");}}class Boy extends Person {void eat() {System.out.println("Boy.eat()");}void speak() {System.out.println("Boy.speak()");}}public class Persons {public static void main(String[] args) {Person p = new Boy();p.eat();p.speak();// The method speak() is undefined for the type Person}}If no override method is defined in the subclass, the method in the parent class is called:
class Person {void eat() {System.out.println("Person.eat()");}}class Boy extends Person {}public class Persons {public static void main(String[] args) {Person p = new Boy();p.eat();}}【Operation results】:
Person.eat()
2. Binding of static methods
Add the static keyword to the above methods and turn them into static methods:
class Person {static void eat() {System.out.println("Person.eat()");}static void speak() {System.out.println("Person.speak()");}}class Boy extends Person {static void eat() {System.out.println("Boy.eat()");}}static void speak() {System.out.println("Boy.speak()");}}class Girl extends Person {static void eat() {System.out.println("Girl.eat()");}static void speak() {System.out.println("Girl.speak()");}}public class Persons {public static Person randPerson() {switch ((int)(Math.random() * 2)) {default: case 0: return new Boy();case 1: return new Girl();}}public static void main(String[] args) {Person[] p = new Person[4];for (int i = 0; i < p.length; i++) {p[i] = randPerson();// Randomly generated Boy or Girl}for (int i = 0; i < p.length; i++) {p[i].eat();}}} 【Operation results】:
Person.eat()
Person.eat()
Person.eat()
Person.eat()
Observation results: for static methods, no matter what subclass object the parent class refers to, the method of the parent class is called.
Mnemonic formula
- Static method: static method looks at the parent class
- Non-static methods: Non-static methods look at subclasses
Summarize
The above is all the content of this article's detailed interpretation of the concept of Java inheritance, and I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!