Basic concepts of abstract classes
A normal class is a fully functional class that generates instantiated objects directly and can contain constructors, normal methods, static methods, constants, and variables. An abstract class means adding the components of an abstract method to the structure of an ordinary class.
So what are abstract methods? All normal methods have a “{}” above them, which represents the body of the method. Methods with a body must be used directly by objects. Abstract methods, on the other hand, refer to methods that have no method body and must be decorated with the keyword abstract.
Classes that have abstract methods are abstract classes, which are declared using the abstract keyword.
Example: Define an abstract class
3 public void fun(){4 system.out.println (); 5 } 6 7 public abstract void print(); } 8 9} 8 9}Copy the code
The use of abstract classes
Let’s start with an example. Example: Directly instantiate objects of abstract classes
3 public void fun(){4 system.out.println (); 5 } 6 7 public abstract void print(); // Abstract method, no method body, 11 11 public class TestDemo {12 13 public static void main(String[] args) {14 A A = new A(); 16 15}}Copy the code
Run:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Cannot instantiate the type A
at com.wz.abstractdemo.TestDemo.main(TestDemo.java:15)
Copy the code
It can be seen from the above that A is abstract and cannot be instantiated directly. Why can’t you instantiate it directly? When a class is instantiated, it means that the object can call properties of the class or let go, but there are abstract methods in abstract classes, and abstract methods don’t have a method body, and they can’t be called without a method body. How can you generate an instantiated object if you can’t make a method call?
The principles for using abstract classes are as follows: (1) The abstract method must be public or protected (because if it is private, it cannot be inherited by a subclass and the subclass cannot implement the method). By default, the abstract method must be public. (2) Abstract classes cannot be instantiated directly, and need to rely on the subclass to adopt the way of upward transformation; (3) An abstract class must have a subclass. Using extends extends, a subclass can inherit only one abstract class. (4) A subclass (if not an abstract class) must override all abstract methods in the abstract class. (If the subclass does not implement the abstract methods of the parent class, the subclass must also be defined as an abstract class.) ;
Example:
3 public void fun(){4 system.out.println (); 5 } 6 7 public abstract void print(); Class B extends A{// class B extends A{// class B extends A{ Override 14 public void print() {// Mandatory Override 15 system.out.println ("Hello World! ); 16 } 17 18 } 19 public class TestDemo { 20 21 public static void main(String[] args) { 22 A a = new B(); A.foo (); // Method overridden by subclasses 25} 26}Copy the code
Running results:
Hello World !
Copy the code
(1) An abstract class inherits a subclass with explicit override requirements, whereas ordinary classes can optionally override methods; (2) The abstract class actually has more abstract methods than the ordinary class, and other components are exactly the same as the ordinary class; (3) Ordinary class objects can be instantiated directly, but the objects of abstract classes must be transformed upward before they can be obtained.
Although a subclass of a class can inherit any ordinary class, but from the practical requirements of development, ordinary classes try not to inherit another ordinary class, but to inherit abstract classes.
3. Restrictions on the use of abstract classes
(1) Is there a constructor in an abstract class? Since there are properties in an abstract class, there must be constructors in an abstract class for the purpose of initializing the properties. In addition, the instantiation of a subclass object still satisfies the order of superclass construction first and then subclass construction.
Here’s an example:
3 public A(){4 system.out.println ("*****A class constructor *****"); 5 } 6 7 public abstract void print(); Class B extends A{// class B extends A{// class B extends A{ Public B(){14 system.out.println ("*****B class constructor *****"); 17} 16 17 @override 18 public void print() {// Mandatory Override 19 system.out.println ("Hello World!" ); 20 } 21 22 } 23 public class TestDemo { 24 25 public static void main(String[] args) { 26 A a = new B(); // Upward transition 27} 28 29}Copy the code
Execution Result:
***** class A constructor ***** ***** class B constructor *****Copy the code
(2) Can abstract classes be declared with final? No, because abstract classes must have subclasses, and final classes cannot have subclasses;
(3) Can abstract classes use static declaration? Let’s start with an example of an external abstract class:
1 public abstract void print(); 2 public abstract void print(); 4 5 } 6 7 class B extends A{ 8 9 public void print(){ 10 System.out.println("**********"); 11 } 12 } 13 public class TestDemo { 14 15 public static void main(String[] args) { 16 A a = new B(); // Uptransition 17 a.plyint (); 18} 19 20}Copy the code
The execution result
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Illegal modifier for the class A; only public, abstract & final are permitted
at com.wz.abstractdemo.A.<init>(TestDemo.java:3)
at com.wz.abstractdemo.B.<init>(TestDemo.java:9)
at com.wz.abstractdemo.TestDemo.main(TestDemo.java:18)
Copy the code
Let’s take another look at the inner abstract class:
1 abstract class A{// define an abstract class 2 3 static abstract class B{// Static definition of the inner class belongs to the outer class 4 public void print(); 5 } 6 7 } 8 9 class C extends A.B{ 10 11 public void print(){ 12 System.out.println("**********"); 13 } 14 } 15 public class TestDemo { 16 17 public static void main(String[] args) { 18 A.B ab = new C(); 19 ab.print(); 20} 21 22}Copy the code
Execution Result:
* * * * * * * * * *Copy the code
As you can see, the external abstract class does not allow static declarations, while the inner abstract class runs with static declarations. An internal abstract class declared static is equivalent to an external abstract class. The form “inner class” represents the class name.
(4) Can I call an abstract class static? Any time you want to execute a static method on a class, you can call it without an object, even for an abstract class. Here’s an example:
3 public static void print(){4 system.out.println ("Hello World!") ); 5 } 6 7 } 8 9 public class TestDemo { 10 11 public static void main(String[] args) { 12 A.print(); 13} 14 15}Copy the code
Running results:
Hello World !
Copy the code
(5) Sometimes external subclasses can be ignored because only a specific system subclass operation is required in an abstract class. Such a design is common in system libraries to hide unwanted subclasses from the user. Here’s an example:
1 abstract class A{// define an abstract class. 4 4 Private static class B extends A{5 6 public void print(){6 system.out.println ("Hello World!") ); 12 public static A getInstance(){13 return new B(); 14 } 15 16 } 17 18 public class TestDemo { 19 20 public static void main(String[] args) { 21 22 23 A A = a.getInstance (); 24 a.print(); 26 25}}Copy the code
Running results:
Hello World !
Copy the code
Application of abstract classes — template design pattern
For example, there are now three kinds of things: (1) robots: charging, working; (2) People: eat, work and sleep. (3) Pigs: eat and sleep. Now it is required to implement a program that can implement the behavior of three different things.
Define an abstract behavior class:
1 public abstract class Action{ 2 3 public static final int EAT = 1 ; 4 public static final int SLEEP = 3 ; 5 public static final int WORK = 5 ; 6 7 public abstract void eat(); 8 public abstract void sleep(); 9 public abstract void work(); 10 11 public void commond(int flags){ 12 switch(flags){ 13 case EAT: 14 this.eat(); 15 break; 16 case SLEEP: 17 this.sleep(); 18 break; 19 case WORK: 20 this.work(); 21 break; 22 case EAT + SLEEP: 23 this.eat(); 24 this.sleep(); 25 break; 26 case SLEEP + WORK: 27 this.sleep(); 28 this.work(); 29 break; 30 default: 31 break; 32} 33} 34}Copy the code
Define a robot class:
1 public class Robot extends Action{2 2 @override 4 public void eat() {5 system.out.println (" Robot "); 6 7 } 8 9 @Override 10 public void sleep() { 11 12 } 13 14 @Override 15 public void work() { 16 System.out.println(" robot works "); 17 18} 19 20}Copy the code
Define a person’s class:
1 public class extends Action{2 2 @override 4 public void eat() {5 system.out.println (); 9 9 @override 10 public void sleep() {11 system.out.println (); 12 13} 14 14 @override 16 public void work() {17 system.out.println (" work "); 18 19} 20 21}Copy the code
Define a pig class:
1 public class Pig extends Action{2 3 @override 4 public void eat() {5 system.out.println (" Pig eats "); 9 9 @override 10 public void sleep() {11 system.out.println (); 12 13 } 14 15 @Override 16 public void work() { 17 18 19 } 20 21 }Copy the code
Test main class:
1 public class AbstractDemo { 2 3 public static void main(String[] args) { 4 5 fun(new Robot()); 6 7 fun(new Human()); 8 9 fun(new Pig()); 10 11 } 12 13 public static void fun(Action act){ 14 act.commond(Action.EAT); 15 act.commond(Action.SLEEP); 16 act.commond(Action.WORK); 17} 18 19}Copy the code
Running results:
Robot charging robot working man eating man sleeping man working pig eating pig sleepingCopy the code
All subclasses must override the specified method if they want to perform normal operations, and the function of the abstract class is the function of a class definition template.