多态:可以理解为事物存在的多种体现形态
如:人:男人,女人
动物:猫,狗,鸟
猫这个动物应该是猫类型的:猫 cat = new 猫();
同时猫也是动物的一种:动物 y = new 猫(); 动物是猫和狗具体事物抽取出来的父类型,父类型指向了子类对象
1、多态的体现
父类的引用指向了自己的子类对象
父类的引用也可以接收自己的子类对象
2、多态的前提
必须是类与类之间有关系,要么继承,要么实现
还有一个前提:存在覆盖
3、多态的好处
多态的出现大大的提高了程序的扩展性
4、多态的弊端
虽然提高了扩展性,但是只能使用父类的引用访问父类中的成员
5、多态的应用
6、多态使用的注意事项
看一个关于多态的例子:
abstract class Teacher
{
public abstract void teach();
public void sleep()
{
System.out.println("睡觉");
}
}
class MathTeacher extends Teacher
{
public void teach()
{
System.out.println("教数学");
}
}
class ChineseTeacher extends Teacher
{
public void teach()
{
System.out.println("教语文");
}
public void sleep()
{
System.out.println("睡觉在沙发上");
}
}
//将代码进一步优化,定义一个工具类,这样就不需要实例化每一个老师对象,直接调用工具类,然后把各种类型的Teacher传进去既可
class TeachTest
{
public static void teach(Teacher t)//Teacher t类型是Teacher由于多态可以直接传MathTeacher等
{
t.teach();
t.sleep();
}
}
class Test
{
public static void main(String[] args)
{
/*
实例化一个新的数学老师
Teacher t = new MathTeacher(); 类型提升,向上转型
t.sleep();
如果想要调用猫的特有方法该怎么做?
强制将父类引用转成子类类型,向下转型
MathTeacher mt = (MathTeacher)t;
mt.teach(); 就可以调用数学老师里面的教学方法
*/
/*
如果要调用类的方法,先实例化一个类,然后分别调用
MathTeacher mt = new MathTeacher();
mt.teach();
mt.sleep();
ChineseTeacher ct = new ChineseTeacher();
ct.teach();
ct.sleep();
发现这样比较麻烦,向上抽取,定义一个新的工具类TeachTest,将方法封装进去
*/
TeachTest tt = new TeachTest();
tt.teach(new MathTeacher());
tt.teach(new ChineseTeacher());
}
}
在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有,编译失败
在运行时期:参阅对象所属的类中是否有调用的方法
简单总结:成员函数在多态调用时,编译看左边,运行看右边
(面试)在多态中成员变量,静态成员函数的特点:
无论编译或运行,都参考左边(引用型变量所属的类)
如:
1 Fu f = new Zi();
2 System.out.println(f.num);//打印的是父类里面的变量num
3 Zi z = new Zi();
4 System.out.println(z.num);//打印的是子类里面的变量num
5 //静态的方法也是一样。
一个集合了接口,多态的例子
/*
类 主板,主板有运行方法run()
一段时间后想要上网 加入网卡类
想要听音乐 加入 声卡类
但是这样一个一个的加入使得代码的扩展性很差,每次都要重新修改很多代码
于是引入一个通用的接口PCI类
所有设备都有打开和关闭功能
让网卡和声卡分别取实现PCI接口,重写成自己的打开和关闭功能
给主板加上一个实现pcirun的方法,传递参数的值为PCI类型的
可以利用多态PCI p = new NetCard();
所以在下面主函数中运行时 创建新的主板对象以后
mb.pcirun(new NetCard());
mb.pcirun(new SoundCard());
就可以分别使用网卡和声卡了,如果以后还要再加入比如显卡
就只需要建立一个显卡类去实现PCI接口,然后直接用主板中的pcirun方法就可以了。
*/
class MainBoard
{
public void run()
{
System.out.println("mainboard run");
}
public void pcirun(PCI p)
{
p.open();
p.close();
}
}
interface PCI
{
public abstract void open();
public abstract void close();
}
class NetCard implements PCI
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
}
}
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.pcirun(new NetCard());
mb.pcirun(new SoundCard());
}
}
/*
这样做的好处:
大大的降低了主板和各种独立设备直接的耦合性
中间用一个PCI接口来连接起来
程序日后非常方便扩展
*/