多态

来源:互联网 发布:mac版lol官网 编辑:程序博客网 时间:2024/06/07 03:28
多态:可以理解为事物存在的多种体现形态。

人:男人,女人    
动物:猫,狗。
猫 x = new 猫();   动物 x = new 猫();


1、多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象。
2、多态的前提
必须是类与类之间有关系。要么继承,要么实现。
通常还有一个前提:存在覆盖。
3、多态的好处
多态的出现大大的提高程序的扩展性。
4,多态的弊端:

虽然提高了扩展性,但是只能使用父类的引用访问父类中的成员。

/*动物,猫,狗。*/abstract class Animal{abstract void eat();}class Cat extends Animal{public void eat(){System.out.println("猫 吃鱼");}public void catchMouse(){System.out.println("猫 抓老鼠");}}class Dog extends Animal{public void eat(){System.out.println("狗 吃骨头");}public void kanJia(){System.out.println("狗 看家");}}class Pig extends Animal{public void eat(){System.out.println("猪 吃饲料");}public void gongDi(){System.out.println("拱地");}}class DuoTaiDemo {public static void main(String[] args) {function(new Cat());function(new Dog());function(new Pig());}//提高函数的复用性public static void function(Animal a)//Animal a = new Cat();{a.eat();}}

第二个问题:如何使用子类特有方法?

      关于类型向上转型

       Animal a = new Cat();//类型提升。 向上转型。
a.eat();


如果想要调用猫的特有方法时,如何操作?
答:强制将父类的引用,转成子类类型。向下转型。
Cat c = (Cat)a;
c.catchMouse();


注意:千万不要出现这样的操作,就是将父类对象转成子类类型。
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化。
Animal a = new Animal();
Cat c = (Cat)a;//不可以将父类对象转成子类类型,故而错误

/*** 如何使用子类特有方法?*/abstract class Animal{abstract void eat();}class Cat extends Animal{public void eat(){System.out.println("吃鱼");}public void catchMouse(){System.out.println("抓老鼠");}}class Dog extends Animal{public void eat(){System.out.println("吃骨头");}public void kanJia(){System.out.println("看家");}}class Pig extends Animal{public void eat(){System.out.println("饲料");}public void gongDi(){System.out.println("拱地");}}class DuoTaiDemo2 {public static void main(String[] args) {function(new Dog());function(new Cat());}public static void function(Animal a)//Animal a = new Cat();{a.eat();//这段代码是可以运行的,传进来的都是Animal类型故而下面的判断不执行/*if(a instanceof Animal){System.out.println("haha");}else */if(a instanceof Cat){Cat c = (Cat)a;c.catchMouse();}else if(a instanceof Dog){Dog d = (Dog)a;d.kanJia();}/*instanceof : 用于判断对象的类型。 对象 intanceof 类型(类类型 接口类型)  */}}

如何将这两类事物进行抽取呢?

/*基础班学生:学习,睡觉。高级班学生:学习,睡觉。可以将这两类事物进行抽取。*/abstract class Student{public abstract void study();public void sleep(){System.out.println("躺着睡");}}class DoStudent{public void doSome(Student stu){stu.study();stu.sleep();}}class BaseStudent extends Student{public void study(){System.out.println("base study");}public void sleep(){ System.out.println("坐着睡");}}class AdvStudent extends Student{public void study(){System.out.println(" adv study");}}class  DuoTaiDemo3{public static void main(String[] args) {DoStudent ds = new DoStudent();ds.doSome(new BaseStudent());ds.doSome(new AdvStudent());//BaseStudent bs = new BaseStudent();//bs.study();//bs.sleep();//AdvStudent as = new AdvStudent();//as.study();//as.sleep();}}






多态中成员函数的特点

在多态中非静态成员函数的特点:

  •     在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
  •     在运行时期:参阅对象所属的类中是否有调用的方法。
    简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。


面试中常考


  在多态中,成员变量的特点:
    无论编译和运行,都参考左边(引用型变量所属的类)。

在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。

package tan;class Fu{static int num = 5;void method1(){System.out.println("fu method_1");}void method2(){System.out.println("fu method_2");}//静态的方法static void method4(){System.out.println("fu method_4");}}class Zi extends Fu{static int num = 8;void method1(){System.out.println("zi method_1");}void method3(){System.out.println("zi method_3");}static void method4(){System.out.println("zi method_4");}}class  DuoTaiDemo4{public static void main(String[] args) {Fu f = new Zi();//父类引用指向子类对象System.out.println(f.num);//输出结果为:5/*为什么父类引用指向子类对象时,输出结果仍然按照父类的呢?在多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。        *///Zi z = new Zi(); //子类的对象调用子类的变量输出结果为:8//System.out.println(z.num);//Fu f = new Zi();//f.method1();//f.method2();//f.method3();  //编译出错:父类无method3方法/*Fu f = new Zi();f.method4(); 调用的是父类引用所属变量的内容Zi z = new Zi();z.method4();调用的是子类引用所属变量的内容总结:在多态中,静态成员函数的特点:无论编译和运行,都参考左边。*///能编译运行,输出//Zi z = new Zi();//z.method1(); -->zi method_1  复写父类中的方法//z.method2(); -->fu method_2  继承了父类中的方法//z.method3(); -->zi method_3  子类特有的方法}}


多态实例:计算机主板扩展

/*需求:电脑运行实例,电脑运行基于主板。*/package tan;//接口的出现增加了功能扩展,同时多态的应用提高了程序扩展性interface PCI{public void Open();public void Close();}class MainBorad{public void run(){System.out.println("主板运行");}public void usePCI(PCI p){//PCI p = new NetCard()//接口型引用指向自己的子类对象。if(p!=null){//判断扩展插槽是否为空p.Open();p.Close();}}}class netCard implements PCI{@Overridepublic void Open() {System.out.println("网卡启动");}@Overridepublic void Close() {System.out.println("网卡关闭");}}class soundCard implements PCI{@Overridepublic void Open() {System.out.println("声卡启动");}@Overridepublic void Close() {System.out.println("声卡关闭");}}public class DuoTaiDemo5 {public static void main(String[] args) {MainBorad m=new MainBorad();m.run();m.usePCI(null);m.usePCI(new netCard());m.usePCI(new soundCard());}}


多态的扩展示例:

/*需求:数据库的操作。数据是:用户信息。1,连接数据库。JDBC  Hibernate2,操作数据库。c create r read  u update  d delete3,关闭数据库连接。*/interface UserInfoDao{public void add(User user);public void delete(User user);}class UserInfoByJDBC implements UserInofDao{public void add(User user){1,JDBC连接数据库。;2,使用sql添加语句添加数据。;3,关闭连接。}public void delete(User user){1,JDBC连接数据库。;2,使用sql添加语句删除数据。;3,关闭连接。}}class UserInfoByHibernate implements UserInfoDao{public void add(User user){1,Hibernate连接数据库。;2,使用sql添加语句添加数据。;3,关闭连接。}public void delete(User user){1,Hibernate连接数据库。;2,使用sql添加语句删除数据。;3,关闭连接。}}class  DBOperate{public static void main(String[] args) {//UserInfoByJDBC ui = new UserInfoByJDBC();//UserInfoByHibernate ui = new UserInfoByHibernate();UserInfoDao ui = new UserInfoByHibernate();ui.add(user);ui.delete(user);}}









0 0