Java object-oriented abstract classes and interfaces
⚡ Preface ⚡ ️
This article is the third article in the object-oriented part. See the links for the first two articles Package and inheritance,Combination and polymorphism . Abstract classes and interfaces are a further step of the parent class in the inheritance relationship. It is easier to understand and master when reading in combination with the previous two articles.
🍉 Blog home page: 🍁 [warm the sun like the wind]🍁
🍉 Boutique Java column [Javase],[Java data structure]
🍉 Welcome to like 👍 Collection ⭐ Message comments 📝 Private letters must be answered 😁
🍉 This article was originally written by [Rufeng Wenyang], and was first launched in CSDN 🙉
🍉 Bloggers will continue to update their learning records. If you have any questions, you can leave a message in the comment area
🍉 The source code involved in the blog and the blogger's daily practice code have been uploaded Code cloud (gitee)
🍅 abstract class
🍓 rule of grammar
In the last article [combination and polymorphism] In the example of printing graphics, we find that the draw method in the parent class Shape does not seem to have any practical work. The main drawing graphics are completed by the draw methods of various subclasses of Shape Like this method without actual work, we can design it as an abstract method. The class containing the abstract method is called abstract class.
matters needing attention:
1. What is abstract method: a method without concrete implementation is modified by abstract
abstract class Shape { abstract public void draw(); }
2. Abstract classes cannot be instantiated (cannot be new)
3. Because it cannot be instantiated, this abstract class can only be inherited
4. Abstract classes can also contain the same members and methods as ordinary classes (like ordinary classes, there is an additional layer of verification)
5. If an ordinary class inherits an abstract class, all abstract methods of the abstract class need to be rewritten in the ordinary class
6. The greatest function of abstract classes is to be inherited
7. If an abstract class a inherits an abstract class B, the abstract class A may not implement the abstract method of the abstract parent class B
8. Combined with the seventh point, when class A is inherited by an ordinary class again, all abstract methods in the two abstract classes a and B must be overridden
9. Abstract classes and methods cannot be modified by final and private (contradictory. Abstract classes cannot be changed after being modified by these two keywords for inheritance and rewriting)
🍓 Role of abstract classes
Abstract classes exist in order to be inherited
The abstract class itself cannot be instantiated. If you want to use it, you can only create subclasses of the abstract class Then let the subclass override the abstract method in the abstract class
Some students may say that ordinary classes can also be inherited and ordinary methods can also be rewritten. Why do you have to use abstract classes and abstract methods?
Such is the case. However, the use of abstract classes is equivalent to an extra check of the compiler
The scenario of using abstract classes is like the above code. The actual work should not be completed by the parent class, but by the child class At this time, if you accidentally misuse it as a parent class,
Using a common class compiler will not report an error However, if the parent class is an abstract class, it will prompt an error when instantiating, so that we can find the problem as soon as possible
The meaning of many grammars is to "prevent errors". For example, final, which we used to use, is similar If the user does not modify the created variable, it is equivalent to a constant?
But in addition, final can let the compiler remind us in time when it is accidentally modified Making full use of compiler verification is very meaningful in practical development
🍅 Interface
Interface is a further step of abstract class Abstract classes can also contain non abstract methods and fields, while the methods contained in interfaces are abstract methods, and fields can only contain static constants An interface is actually an abstract class with more specific performance and multiple inheritance functions
🍓 matters needing attention
1. Use interface to decorate
interface IA {}
2. Ordinary methods in the interface cannot have specific implementation (if they have to be implemented, they can only be modified by the keyword default, which has the same function as ordinary classes)
3. There can be static methods in the interface
4. All methods in the interface are public by default
5. The abstract method is public abstract by default
6. The interface cannot be instantiated either (when the interface is a further step of the abstract class, the abstract class cannot be instantiated, and the interface is the same)
7. The relationship between classes and interfaces is realized through the keyword implements
8. When a class implements an interface, it must rewrite the abstract methods in the interface
9. The member variable in the interface is modified by public static final by default
interface IShape { void draw(); //Abstract method. It is modified by public abstract by default int num = 10; //public static final int num = 10; }
10. When a class implements an interface and rewrites this method, it must be preceded by public (because the abstract method in the interface is modified by public by default, the access permission of the rewriting method of the subclass should be greater than or equal to the access permission of the rewriting method of the parent class)
An incorrect code
interface IShape { abstract void draw() ; // Even if you don't write public, it's public } class Rect implements IShape { void draw() { //public should be added System.out.println("□") ; //The permission is more strict, so it cannot be overwritten. } }
11. A class can inherit an abstract class or ordinary class through the keyword extends, but only one class can be inherited; However, multiple interfaces can be implemented with the keyword implements, separated by commas
12. The relationship between classes is operated through extensions, and the relationship between classes and interfaces is operated through implements. What kind of relationship will exist between interfaces?
Extensions can be used between interfaces to operate their relationships. At this time, it means: extension (equivalent to inheritance between classes, so use the extensions keyword)
An interface B expands the functions of another interface A through extensions. At this time, when A class C implements this interface B through implements, the rewritten method is not only the abstract method of B, but also the abstract method extended from the C interface
🍓 Understanding interface
Sometimes we need to make a class inherit from multiple parent classes at the same time This is achieved in some programming languages through multiple inheritance
However, only single inheritance is supported in Java, and a class can only extend a parent class Multiple interfaces can achieve similar effects at the same time
Now we represent a group of animals by classes
class Animal { protected String name; public Animal(String name) { this.name = name; } }
In addition, we provide another set of interfaces, which respectively mean "those who can fly", "those who can run" and "those who can swim"
interface IFlying { void fly(); } interface IRunning { void run(); } interface ISwimming { void swim(); }
Next, we create several specific animals
Cats can run
class Cat extends Animal implements IRunning { public Cat(String name) { super(name); } @Override public void run() { System.out.println(this.name + "Running on four legs"); } }
Fish can swim
class Fish extends Animal implements ISwimming { public Fish(String name) { super(name); } @Override public void swim() { System.out.println(this.name + "He is swimming with his tail"); } }
Frogs can run and swim (amphibians)
class Frog extends Animal implements IRunning, ISwimming { public Frog(String name) { super(name); } @Override public void run() { System.out.println(this.name + "Jumping forward"); } @Override public void swim() { System.out.println(this.name + "He is kicking his legs to swim"); } }
There is also a magical animal called "duck", which lives in water, land and air
class Duck extends Animal implements IRunning, ISwimming, IFlying { public Duck(String name) { super(name); } @Override public void fly() { System.out.println(this.name + "Flying with wings"); } @Override public void run() { System.out.println(this.name + "Running on two legs"); } @Override public void swim() { System.out.println(this.name + "Floating on the water"); } }
The above code shows the most common usage in Java object - oriented programming: a class inherits a parent class and implements multiple interfaces at the same time
The meaning of inheritance expression is is - a semantics, while the meaning of interface expression is xxx
Cat is a kind of animal, which can run
Frog is also an animal. It can run and swim
Duck is also an animal. It can run, swim and fly
What are the benefits of this design? Keep the benefits of polymorphism in mind and let the program forget the type With an interface, users of a class don't have to focus on specific types, but only on whether a class has certain capabilities
For example, now implement a method called "walking"
public static void walk(IRunning running) { running.run(); }
Inside the walk method, we don't pay attention to which animal it is, as long as the parameter can run
Cat cat = new Cat("kitten"); walk(cat); Frog frog = new Frog("Little frog"); walk(frog); // results of enforcement The kitten is running on four legs The little frog is jumping forward
Even the parameter can not be "animal", as long as it can run!
class Robot implements IRunning { private String name; public Robot(String name) { this.name = name; } @Override public void run() { System.out.println(this.name + "Running on wheels"); } } Robot robot = new Robot("robot"); walk(robot); // results of enforcement The robot is running on wheels
🍓 Two interfaces are commonly used
🍉Comparable
We use the following code when sorting the array:
import java.util.Arrays; public class Test1 { public static void main(String[] args) { int[]arr={1,5,3,4,9}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } }
But if we sort the object array, we can't just sort it by such a simple method. Next, let's see how to sort the object array.
import java.util.Arrays; class Student { public int age; public double score; public String name; public Student(int age, double score, String name) { this.age = age; this.score = score; this.name = name; } @Override//This method is overridden to print the specific members of the object array public String toString() { return "Student{" + "age=" + age + ", score=" + score + ", name='" + name + '\'' + '}'; } } public class Test1 { public static void main(String[] args) { Student[] students=new Student[3]; students[0]=new Student(18,85.0,"A"); students[1]=new Student(17,80.5,"B"); students[2]=new Student(19,90.3,"C"); System.out.println(Arrays.toString(students)); Arrays.sort(students); System.out.println(Arrays.toString(students)); } }
The above exception occurred when sorting the object array, so why?
Because there are multiple member attributes in the object, you cannot determine which member attribute to arrange when sorting the object array
Therefore, we introduce the comparator to specifically solve the problem of sorting the object array. We need to connect the class to the interface Comparable (pay attention to the type of comparison written in < > after the interface) and rewrite the compareTo method to sort the specified elements of the object array
class Student implements Comparable<Student> { public int age; public double score; public String name; public Student(int age, double score, String name) { this.age = age; this.score = score; this.name = name; } @Override public String toString() { return "Student{" + "age=" + age + ", score=" + score + ", name='" + name + '\'' + '}'; } ====================================================================================== @Override public int compareTo(Student o) { if(this.age>o.age) return 1; else if(this.age==o.age) return 0; else return -1; } }
//Operation results:
================================================================================= The rewriting method above can also be written in the following form @Override //Ascending order public int compareTo(Student o) { return this.age - o.age; } @Override //Descending order public int compareTo(Student o) { return this.age - o.age; }
For the compareTo method, whoever calls it is this, and the passed parameter is o. if the returned value is greater than 0, it means this is greater than o; Equal to 0, both equal; Less than 0 means this is less than o. If you need to arrange in descending order, change the positions of this and o.
If you want to compare strings or other classes, you need to call the compareTo method provided in the class for comparison, such as string:
================================================================================= @Override public int compareTo(Student o) { return this.name.compareTo(o.name); }
Sort by the age of the two students
public class Test1 { public static void main(String[] args) { Student student1=new Student(18,85.0,"A"); Student student2=new Student(17,80.5,"B"); System.out.println(student1.compareTo(student2)); } } //Operation results: 1 It means that the first student is older than the second student( o1.data>o2.data Returns a positive number, o1.data==o2.data Return 0, o1.data<o2.data (returns a negative number)
Therefore, if you want to compare the size of user-defined types of data, you must implement a comparable interface, but this interface has a big disadvantage: it is very intrusive to classes. Once written, you don't dare to change it easily. Therefore, Comparator is often used in practice. Let's talk about Comparator.
🍉 Comparator
public interface Comparator<T> { int compare(T o1, T o2); ... }
By calling the above interface, you can compare the specified elements in the object array. The following is the code implementation. In this way, the attributes of the class to be compared are extracted from the original class, which greatly reduces the invasiveness of the class
import java.util.Comparator; class AgeComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.age-o2.age; } } class ScoreComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return (int)(o1.score-o2.score); } } class NameComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.name.compareTo(o2.name); } } class Student { public int age; public double score; public String name; public Student(int age, double score, String name) { this.age = age; this.score = score; this.name = name; } @Override public String toString() { return "Student{" + "age=" + age + ", score=" + score + ", name='" + name + '\'' + '}'; }
Let's first use a comparator to compare the ages of the two students:
public class Test1 { public static void main(String[] args) { Student student1=new Student(18,85.0,"A"); Student student2=new Student(17,80.5,"B"); AgeComparator ageComparator = new AgeComparator(); System.out.println(ageComparator.compare(student1,student2)); } } //Operation results: 1 It means that the first student is older than the second student( o1.data>o2.data Returns a positive number, o1.data==o2.data Return 0, o1.data<o2.data (returns a negative number)
Sort student array:
public class Test1 { public static void main(String[] args) { Student[] students=new Student[3]; students[0]=new Student(18,85.0,"A"); students[1]=new Student(17,80.5,"B"); students[2]=new Student(19,90.3,"C"); AgeComparator ageComparator = new AgeComparator(); Arrays.sort(students,ageComparator); System.out.println("Sort by age:"); System.out.println(Arrays.toString(students)); ScoreComparator scoreComparator=new ScoreComparator(); Arrays.sort(students,scoreComparator); System.out.println("Sort by score:"); System.out.println(Arrays.toString(students)); NameComparator nameComparator=new NameComparator(); Arrays.sort(students,nameComparator); System.out.println("Sort by name:"); System.out.println(Arrays.toString(students)); } } //The default sorting is ascending. If you need to arrange in descending order, just exchange the positions of o1 and o2 for the same reason.
Operation results:
⚡ Last words ⚡ ️
It's not easy to summarize. I hope uu you won't be stingy with your work 👍 Yo (^ u ^) yo!! If you have any questions, please comment and correct them in the comment area 😁