欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java学习笔记-多态

程序员文章站 2024-03-21 19:07:46
...

面向对象三大特征之一,编译类型和运行类型不一致,这种现象叫做多态

定义

某一类事物的多种存在形态

  • 例:动物中猫,狗
  • 猫这个对象对应的类型是猫类型
    • 猫x = new 猫();
  • 同时猫也是动物中的一种,也可以把猫称为动物
    • 动物 y = new 猫();
    • 动物是猫和狗具体事物中抽取出来的父类型
    • 父类型引用指向了子类对象

理解

体现:父类或者接口的引用指向或者接收自己的子类对象

作用:多态的存在提高了程序的扩展性和后期可维护性

前提:

  • 需要存在继承或者实现关系
  • 要有覆盖操作

好处:多态的出现大大的提高程序的扩展性

弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员

特点

非静态成员函数:

  • 编译时:要查看引用变量所属的类中是否有所调用的成员
  • 在运行时:要查看对象所属的类中是否有所调用的成员

成员函数在多态调用时,编译看左边,运行看右边

成员变量:

  • 只看引用变量所属的类

静态成员:

  • 只看引用变量所属的类

多态

class BaseClass{···}
class SubClass extends BaseClass{···}
···
BaseClass bc = new SubClass();
···
  • 在上述示例中,将子类的对象赋值给父类,这叫做向上转型,由系统自动完成。bc在编译时候属于BaseClass类型,而运行时候则为SubClass类型,这就出现了多态。当bc调用实例变量时,将调用父类的实例变量,这是由于对象的实例变量不具备多态性,bc只可以调用父类中存在的方法,但是是在子类中调用,若子类重写了父类的方法,那么调用的就是被重写后的方法,如果没被重写,那么就直接调用继承到的方法,对于仅仅存在于子类中的方法,若使用bc去调用,那么则会编译报错

  • 多态:相同类型的变量、调用同一个方法时呈现出多种不同的行为特征,这就是多态

  • 引用类型之间的转换只能在具有继承关系的两个类型之间,如果试图把一个父类实例转化成子类类型,则这个对象必须实际上是子类类型才可以(即编译类型为父类类型,而运行类型为子类类型)

  • instanceof:为了避免ClassCastException异常,使用instanceof先进行判断在进行类型转换。instanceof前一个操作数通常为一个引用类型变量,后一个操作数通常是一个类(也可以是接口),用于判断前面的对象是否是后面的类或者其子类、实现的实例。如果是则返回true,否则返回false。如果instanceof运算符前面的操作数的编译类型与后面的类不同,或者与后面的类不具备父子继承关系,则会引起编译错误

if ( objPri instanceof String )
{
	String str = (String) objPri;
}

转型

能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换
多态自始至终都是子类对象在做着变化

在多态中存在着转型操作,通常称为向上转型和向下转型
例如存在Cat继承自Animal
那么,将一个Cat对象赋值给Animal就属于向上转型

Animal animal = new Cat(); //向上转型

如果将父类引用转化为子类类型,这种现象称之为向下转型

Cat cat = (Cat)animal; //向下转型

instanceof关键字

用于判断对象的类型

格式:
对象 intanceof 类型(类类型 接口类型)

public static void func(Animal a) {
    if(a instanceof Cat){
        Cat c = (Cat)a;
        ···
    }
}

多态实例

interface PCI {
	public void open();
	public void close();
}

class MainBoard{

	public void run() {
		System.out.println("mainboard run ");
	}

	public void usePCI(PCI p) {
		if(p != null){
			p.open();
			p.close();
		}
	}
}

class NetCard implements PCI {

	public void open() {
		System.out.println("netcard open");
	}

	public void close(){
		System.out.println("netcard close");
		method();
	}
}

class SoundCard implements PCI {

	public void open() {
		System.out.println("SoundCard open");
	}

	public void close() {
		System.out.println("SoundCard close");
	}
}

class Test 
{
	public static void main(String[] args) {
		MainBoard mb = new MainBoard();
		mb.run();
		mb.usePCI(null);
		mb.usePCI(new NetCard());
		mb.usePCI(new SoundCard());
	}
}