In depth study of java object-oriented polymorphism and internal classes

Posted by Dang on Mon, 03 Jan 2022 05:31:00 +0100

I polymorphic

1. Class polymorphism

Requirements:

Demand: teachers go to work by bike

Analysis: teachers, bicycles

Demand upgrade / iteration: Bicycle - > car

Steps:

1. Create a Car class and write start and stop

2. Write open and close based on the original Teacher class

Note: violation of OCP principles

OCP - opening and closing principle:

O - open: it is welcome to create classes when requirements are upgraded

C - close: when upgrading requirements, changing the original code is rejected

Note: when upgrading requirements, try not to change the previous classes, otherwise it is easy to bug

Demand upgrading / iteration: Bicycle - > car - > plane

Step: create a Plane class to inherit Vehicle

Code parsing:

package com.dream.test01;

public class Test01 {

	public static void main(String[] args) {

		Teacher t = new Teacher();
		
		//Class polymorphism: the subclass object points to the parent class reference
		//The address of the subclass object in the heap is stored in the parent class reference
		Teacher t = new Teacher();
		
		Vehicle v1 = new Bick();
		Vehicle v2 = new Car();
		Vehicle v3 = new Plane();
		
		t.open(v1);
		System.out.println("Enjoy the scenery along the way...");
		t.close(v1);
		
		System.out.println("---------------");
		
		t.open(v2);
		System.out.println("Drive carefully...");
		t.close(v2);
		
		System.out.println("---------------");
		
		t.open(v3);
		System.out.println("Enjoy the scenery along the way...");
		t.close(v3);
	}
}
package com.dream.test01;

public abstract class Vehicle {
	
	public abstract void start();
	public abstract void stop();
}
package com.dream.test01;

public class Teacher {

	public void open(Vehicle v){
		v.start();
	}
	
	public void close(Vehicle v){
		v.stop();
	}
	
}
package com.dream.test01;

public class Bick extends Vehicle{

	@Override
	public void start(){
		System.out.println("Bicycle: hold the handrail and step on the foot pedal");
	}
	
	@Override
	public void stop(){
		System.out.println("Bicycle: pinch the handbrake~~~");
	}
}
package com.dream.test01;

public class Car extends Vehicle{
	
	@Override
	public void start(){
		System.out.println("Car: one button start, step on the accelerator");
	}
	
	@Override
	public void stop(){
		System.out.println("Car: step on the brake and stop~~");
	}

}
package com.dream.test01;

public class Plane extends Vehicle{

	@Override
	public void start() {
		System.out.println("Aircraft: one click start, refueling door, pull the wing~~~");
	}

	@Override
	public void stop() {
		System.out.println("Aircraft: Skydiving~~~");
	}

}

Output:

/*
Bicycle: hold the handrail and step on the foot pedal
 Enjoy the scenery along the way
 Bicycle: pinch the handbrake~~~
---------------
Car: ignition start
 Drive carefully
 Car: step on the brake
---------------
Aircraft: one click start, refueling door, pull the wing~~~
Enjoy the scenery along the way
 Aircraft: Skydiving~~~
*/

2. Interface polymorphism

Requirements:

Connect the mouse and hard disk to the computer

Code implementation:

package com.study.test03;

public class Test01 {
	public static void main(String[] args) {
	
        //Interface polymorphism: the object of the implementation class points to the reference of the interface
		//The reference of the interface stores the address of the implementation class object to open up space in the heap
		Computer computer = new Computer();
		
		IUSB usb1 = new Mouse();
		computer.connection(usb1);
		
		System.out.println("--------------------");
		
		IUSB usb2 = new Disk();
		computer.connection(usb2);
		
		System.out.println("--------------------");
		
		IUSB usb3 = new Keyboard();
		computer.connection(usb3);
		
		System.out.println("--------------------");
		
	}
}
//Define USB interface
package com.study.test03;

public interface IUSB {
	
	public void use();
}
//Define the interface methods implemented by Mouse, Disk and keyboard
package com.study.test03;

public class Mouse implements IUSB{

	@Override
	public void use() {
		System.out.println("Mouse: point to point");	
	}

}
package com.study.test03;

public class Disk implements IUSB{

	@Override
	public void use() {
		System.out.println("Hard disk: storing things");
	}

}
package com.study.test03;

public class Keyboard implements IUSB{

	@Override
	public void use() {
		System.out.println("Keyboard: Typing");
	}

}
//Define interface user Computer
package com.study.test03;

public class Computer {
	
	public void connection(IUSB usb) {
		
		System.out.println("Connection succeeded!");
		usb.use();
		
	}
	
}

Output:

/*
Connection succeeded!
Mouse: point to point
--------------------
Connection succeeded!
Hard disk: storing things
--------------------
Connection succeeded!
Keyboard: Typing
--------------------
*/

II Object transformation

1. Upward transformation

Subclass type to parent type

You can call the non privatized property of the parent class

You can call a non privatized method of the parent class

You can call a subclass to override the method of the parent class

Subclass properties and methods cannot be called

Note: upward transformation is polymorphism

The disadvantage of polymorphism: you can't call the subclass's own properties and methods

Code implementation:

package com.dream.test03;

public class Test01 {
	
	public static void main(String[] args) {
		
		A a = new B();
		
		System.out.println(a.aAtrr);
		a.aMethod();
		a.method();
	}

}
package com.dream.test03;

public class A {
	
	String aAtrr = "Parent class properties";
	
	public void aMethod(){
		System.out.println("Parent method");
	}
	
	public void method(){
		System.out.println("Parent method");
	}

}
package com.dream.test03;

public class B extends A{

	String bAtrr = "Subclass properties";

	public void bMethod(){
		System.out.println("Subclass method");
	}
	
	@Override
	public void method(){
		System.out.println("Subclasses override methods of the parent class");
	}

}

2. Upward transformation

Parent class type

be careful:

1. ClassCastException - type conversion exception will appear if the downward transformation is not good

2. instanceof judgment must be used for downward transformation

Code implementation:

package com.dream.test04;

public class Test01 {
	
	public static void main(String[] args) {
		
		Animal an = new Dog();//Upward transformation
		
		if(an instanceof Cat){//Determine whether the object pointed to by an reference is of Cat type
			
			Cat cat = (Cat) an;//Downward transformation
			cat.shout();
			
		}else if(an instanceof Dog){//Judge whether the object pointed to by an reference is of Dog type
			
			Dog dog = (Dog) an;//Downward transformation
			dog.eat();
		}
		
	}

}
package com.dream.test04;

public class Animal {

}
package com.dream.test04;

public class Cat extends Animal{

	public void shout(){
		System.out.println("cat ~~~");
	}
}
package com.dream.test04;

public class Dog extends Animal{

	public void eat(){
		System.out.println("Gnaw a bone~~~");
	}
}

III Inner class

1. Member internal class

characteristic:

You can call all properties in an external class

Code implementation:

package com.dream.outter_inner_01;

import com.dream.outter_inner_01.Outter.Inner;

public class Test01 {
	
	public static void main(String[] args) {

		//Create member inner class object
		Inner inner = new Outter().new Inner();
		
		//Call method
		inner.method();
        
	}
}

package com.dream.outter_inner_01;

//External class
public class Outter {
	
	private 	String str1 = "aaa";
				String str2 = "bbb";
	protected 	String str3 = "ccc";
	public 		String str4 = "ddd";
	final 		String str5 = "eee";
	static 		String str6 = "fff";

	//Member inner class
	class Inner{
		
		private String str1 = "Properties within members~~~";
		
		public void method(){
			System.out.println("Methods in inner classes of members");
			System.out.println(this.str1);
			System.out.println(Outter.this.str1);//Calling properties of an external class
			System.out.println(str2);//Outter.this.str2
			System.out.println(str3);//Outter.this.str3
			System.out.println(str4);//Outter.this.str4
			System.out.println(str5);//Outter.this.str5
			System.out.println(str6);//Outter.str6
		}
	}
}

2. Static internal class

characteristic:

Only static properties of external classes can be called

Code implementation:

package com.dream.outter_inner_02;

import com.dream.outter_inner_02.Outter.Inner;

public class Test01 {
	
	public static void main(String[] args) {

		//Create a static inner class object (without creating an outer class object)
		Inner inner = new Outter.Inner();
		
		//Call method
		inner.method();
	
	}
}

package com.dream.outter_inner_02;

//External class
public class Outter {
	
	private 	String str1 = "aaa";
				String str2 = "bbb";
	protected 	String str3 = "ccc";
	public 		String str4 = "ddd";
	final 		String str5 = "eee";
	static 		String str6 = "fff";
	

	//Static inner class
	static class Inner{
		
		public void method(){
			System.out.println("Methods in static inner classes");
			//A static inner class cannot call a member variable of an outer class
//			System.out.println(str1);
//			System.out.println(str2);
//			System.out.println(str3);
//			System.out.println(str4);
//			System.out.println(str5);
			System.out.println(str6);//Outter.str6
		}
	}	
}

3. Interface internal class

characteristic:

The bottom layer of interface internal class is static internal class

Code implementation:

package com.dream.outter_inner_03;

import com.dream.outter_inner_03.Outter.Inner;

public class Test01 {
	
	public static void main(String[] args) {

		//Create an interface internal class object
		Inner inner = new Outter.Inner();
		
		//Call method
		inner.method();
	}
}

package com.dream.outter_inner_03;

//Interface
public interface Outter {
	
	//Interface internal classes add public static by default
	class Inner{
		public void method(){
			System.out.println("Methods in classes inside interfaces");
		}
	}	
}

4. Local internal class

Code implementation:

package com.dream.outter_inner_04;

public class Test01 {
	
	public static void main(String[] args) {

		//Create an object of an external class
		Outter outter = new Outter();
		
		//Call method
		outter.function();
		
	}
}

package com.dream.outter_inner_04;

//External class
public class Outter {
    
	public void function(){
		int i = 100;
		//Local variables in local internal class calling methods, jdk1 The attribute in 8 defaults to final constant
    	/*Reason: it is related to the life cycle of the Inner class.
    	final The modified local variable is a constant and is placed in the constant pool,
    	It will not be recycled after the function() method is used,
    	Ensure that when the method() of the Inner class calls the local variable i, it still exists and can be called
    	*/
		//Local inner class
		class Inner{
			public void method(){
				System.out.println("Methods in local inner classes" + i);
			}
		}
		
		//Create an object of a local inner class
		Inner inner = new Inner();
		//Call method
		inner.method();
		
	}	
}

5. Anonymous inner class

Anonymous inner classes in abstract classes

Code implementation:

package com.dream.outter_inner_06;

public class Test01 {
	
	public static void main(String[] args) {
		
		//1. Create an anonymous subclass, inherit A, and override method
		//2. Create an anonymous subclass object and assign it to the reference of the parent class
		A a = new A() {
			@Override
			public void method() {
			}
		};	
	}
}

package com.dream.outter_inner_06;

public abstract class A {
	
	public abstract void method();

}

Anonymous inner class in interface

Code implementation:

package com.dream.outter_inner_06;

public class Test02 {
	
	public static void main(String[] args) {

		//1. Create an anonymous implementation class to implement the method in I1
		//2. Create an object of anonymous implementation class and point to the reference of the interface
		I1 i1 = new I1() {
			@Override
			public void method() {
			}
		};
		
		
	}

}

package com.dream.outter_inner_06;

public interface I1 {

	public void method();
}

6. Summary of application scenarios of internal classes

Application scenario 1 of internal class:

If the object of a class is only used in another class, you can consider turning the class into a member inner class or a static inner class;

If the inner class needs to use all the attributes of the outer class, it will become a member inner class;

If the inner class only uses the static attributes of the outer class, the given class will become a static inner class;

Application scenario 2 of internal class:

If the object of a class is only used in the method of another class, you can consider turning the class into a local internal class. Generally, this design idea is not used;

Application scenario 3 of internal class:

If the object of a class is only used in the interface, you can consider turning the class into an internal class of the interface. Generally, this design idea is not used;

Application scenario 4 of internal class:

If an object of an abstract class subclass or an interface implementation class object is used only once, you can consider using an anonymous inner class;

Topics: Java OOP interface Polymorphism object