[JAVA · Elementary]: 10. Как лучше понять полиморфизм

Говоря о полиморфизме, он должен быть неотделим от двух других функций: инкапсуляции и наследования. И на них основан полиморфизм, и они тесно связаны. В моей памяти, каждый раз, когда я изучаю объектно-ориентированный, он неотделим от этих трех характеристик.Это ключевой момент объектно-ориентированного, и, конечно, это также трудность. Тем не менее, они похожи на слой оконной бумаги, пока есть зазор, вы можете полностью понять, что такое объектно-ориентированный. Давайте взглянем на некоторые введения в полиморфизм:

что это такое

Литературная перспектива: на тысячу читателей приходится тысяча и один Гамлет;

С точки зрения руководителя компании: одну и ту же задачу, поставленную начальником, каждый человек выполняет по-своему;

Профессиональная точка зрения: несколько объектов одного типа вызывают разные реакции и эффекты при получении одного и того же сообщения;

Из формы кода: объектная переменная родительского класса вызывает метод, переписанный в подклассе (примечание: часто есть родительский класс, и у него несколько подклассов, и некоторые подклассы родительского класса переписаны в этих подклассах одновременно время. метод);

Вывод: предпосылкой полиморфизма является наличие родительского класса и нескольких подклассов.


что делать?

Объектная переменная родительского класса может ссылаться на объект этого класса или объект подкласса.

           Поскольку класс Object является суперкорневым классом (классом-предком), его объектные переменные могут ссылаться на объекты всех классов.

           Специальный оператор: атрибут instanceof

           Примечание. Может ли объектная переменная подкласса ссылаться на объект родительского класса? 

           Ответ: нет

           Для этого его нужно отлить.

То есть преобразование типа объекта делится на следующие два типа:

           1) Восходящее преобразование: объект подкласса может быть напрямую назначен объектной переменной родительского класса. 

Это явление также известно как автоматическое преобразование типов. 

           2) Нисходящее преобразование: привести ссылку родительского класса к ссылке подкласса. 

ПРИМЕЧАНИЕ. Он должен быть брошен.

              Формат: (имя типа) объектная переменная;

Когда объектная переменная родительского класса ссылается на объект подкласса, спросите: может ли объектная переменная родительского класса напрямую вызывать уникальный метод подкласса?

           Ответ: нет.

           Например: Animal — это родительский класс, Dog — подкласс, а метод getName() — это метод, специфичный для подкласса Dog.

                    Следовательно, когда есть Animal a = new Dog();,

                    Тогда a.getName(); правильно? 

                    Ответ: Ложь.  

           В: Тогда как получить доступ?

           Ответ: Вам нужно сначала произнести заклинание (подавленный)

              Объектная переменная имени класса подкласса = (имя класса подкласса) объектная переменная родительского класса;

              即: Собака d = (Собака) а;

              После этого d.getName(); На этом этапе правильно.

При каких обстоятельствах вам нужно привести (восстановить) (понизить) ссылку на объект?

           1) Полиморфизм должен иметь место:

              Объектная переменная родительского класса ссылается на объект подкласса.

              Объект obj = новый Студент();

           2) Должен хотеть получить доступ (вызвать) уникальные свойства или методы объектов подкласса.

              Переменная объекта родительского класса.Уникальный метод (атрибут) объекта подкласса;//Неправильно.

              Stringstr = obj.getSchool();//Неправильно. 

              ((имя класса подкласса) объектная переменная родительского класса). Уникальный метод (свойство) объекта подкласса; //Верно.

              Stringstr = ((Student)obj).getSchool(); // Верно.

  //Полиморфизм: объектная переменная родительского класса ссылается на объект подкласса.

Демо

<span style="font-size:18px;"><span style="font-size:18px;">public class AnimalsTest {
	public static void main(String[] args) {
		Animal a = new Animal("动物");
		
		Dog d1 = new Dog("狗", "旺财", true, 2);
		Cat c1 = new Cat("猫", "豆豆", "blue");
		
		System.out.println( a );
		System.out.println( d1 );
		System.out.println( c1 );
		
		boolean flag = a instanceof Animal ; //判断a属于Animal类型吗
		System.out.println( flag );
		
		flag = a instanceof Dog;
		System.out.println( flag );
		
		flag = d1 instanceof Dog;
		System.out.println( flag );
		
		flag = d1 instanceof Animal;  //当结果为true时,说明它们之间存在继承关系。
		System.out.println( flag );
		
		//多态: 父类的对象变量引用了子类的对象。
		Animal a1 = new Dog("狗", "ABC", false, 3);
		//System.out.println( a1.getName() ); //调用a1的 getName()方法. 此时,它会去Animal类中找 getName()方法。若找不到,则报错。
	
		//判断a1是否拥有Dog类的特性,若有,则还原。
		if( a1 instanceof Dog ){
			Dog dd = (Dog)a1; //将a1强制转换为Dog类型。
			System.out.println( dd.getName() );
		}
		
		System.out.println("程序结束。");
	}
}
</span></span>

Что ты делаешь?

При вызове метода с точки зрения исходного кода невозможно определить, метод какого объекта вызывается. Только во время выполнения программы это можно определить из фактического объекта, на который ссылается объектная переменная.

какой объект. Это явление называется динамической привязкой (связыванием).

Вывод. Предпосылкой динамического связывания является:

1) Происходит наследование, и родительский класс имеет несколько подклассов.

2) В каждом подклассе переопределяется один и тот же метод, унаследованный от родительского класса.

3) Возникает полиморфизм, то есть: переменная объекта родительского класса ссылается на разные объекты подкласса.

4) 父类的对象变量调用了重写的方法,即: 发生了动态绑定。从而实现了多的价值。

Demo

<span style="font-size:18px;"><span style="font-size:18px;">//由于此程序代码较多,只截取显示结果类:
package com.hqg.oop.d37.a3;

import com.hqg.oop.d37.a2.Circle;
import com.hqg.oop.d37.a2.Rectangle;
import com.hqg.oop.d37.a2.Shape;
import com.hqg.oop.d37.a2.Triangle;

//多态的应用
public class ShapesTestNew {
	public static void main(String[] args) {    
		//声明并创建一个Shape类的数组,用来存放6个平面图形对象。
		int x = (int)( 20 * Math.random()) + 1;  
		Shape[] ss = new Shape[ x ];  
		
		//初始化: 创建6个平面图形对象并存放到数组的元素中。
		for( int i = 0;  i < ss.length;  i++ ){ 
			ss[i] = createShape();	     // 将方法返回的结果赋给 ss[i]
		}
		
		//求所有图形的面积总和
		double totalArea = 0;   		 
		totalArea = sumArea( ss );  //将反馈的结果赋给 totalArea 变量
		System.out.println("\n以上所有图形的面积总和为: " + totalArea );  
	
	} // 结束程序的运行。
	
	//方法: 求所有图形的面积总和
	public static double sumArea( Shape[] shapes ){  
		double sumArea = 0;  
		for( int i = 0; i < shapes.length;  i++ ){   
			sumArea += shapes[i].area(); //动态绑定。在程序运行期间求每个图形的面积并累加起来。			
			String str = shapes[i].toString(); //当前这个图形的全部信息			System.out.println( str );  
			System.out.println("--------------------------------------------------");  
		} 
		
		return sumArea ;  
	}
	
	//方法: 用来产生 Circle或Triangle或Rectangle三种类的对象之一。
	public static  Shape  createShape(){ 
		int n = (int)( 3 * Math.random()); //[0, 1, 2]   		
		switch( n ){ 
			case 0 : 
				double r = Math.round( 10 * Math.random() * 10 ) / 10.0 ;
				return new Circle("圆", r);   
				
			case 1 : 
				int l = (int)( 99 * Math.random()) + 1;
				int w = (int)( 69 * Math.random()) + 1;
				return new Rectangle("长方形", l , w );  
				
			case 2 : 
				int a = (int)( 33 * Math.random() ) + 1;
				int h = (int)( 53 * Math.random() ) + 1;
				return new Triangle("三角形", a, h );  
				
			default : 
				return null;
		}
	}
}</span></span>

为什么?

关于面向对象的三大特性,为了更好地理解我们为什么要用它,很有必要知道它带来的好处。当然,站在巨人的肩膀上学习总是高效的,分享一下:

封装性: 安全性和重用性。

继承性: 高效性和重用性。

多态性: 统一性(有机性)和高效性。

对于这三大特性的理解不同,可能会有不同的体会,例如:大自然不同的风景呈现,我们享受到的也不同,如果每天都面对着同一幅场景,后果是很可怕的。要想更好的理解,不断地实践是很不错的选择呢!


业务思想

学习的目的是为了更好地实践,要想在不断进行的项目中可以完成的更好、更为的轻松,这是离不开多态的。我们可以从最后一个demo中,看出加上动态绑定的图形选择,可以很有效的避免我们敲出很多图形的初始化代码,很高效,而且重复的初始化图形,很容易把我们惹毛的(当然这是开玩笑的),而我们要做的就是,尽量减少我们的工作负担,更为高效、轻松的完成。

多态,你一生都离不开的两个字,无论在哪里。


      



Supongo que te gusta

Origin blog.csdn.net/u013047005/article/details/50876327
Recomendado
Clasificación