一、面向对象——多态——概念
1、概念:某一类事物的多种存在形态。 例如: 猫 m = new 猫(); 狗 n = new 狗(); 动物 a = new 猫(); 动物 a = new 狗(); 动物是猫和狗具体事物中抽取出来的父类型; 这里父类引用指向了子类对象。二、面向对象——多态——扩展性
1、多态的代码体现形式: 父类的引用指向了子类对象(父类的引用接收子类的对象)。 2、多态的前提: A、类与类之间存在关系——继承或者实现; B、存在覆盖。 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) { Animal c = new Cat(); Animal d = new Dog(); Animal p = new Pig(); function(c); function(d); function(p); } public static void function(Animal a) { a.eat(); //a.catchMouse();//编译失败:因为父类中没有改方法,不能覆盖。 } }
三、面向对象——多态——转型
1、向上转型:
当父类引用指向自己的子类对象时,将子类类型提升为父类类型。
2、向下转型:
当父类引用指向自己的子类对象时,将父类引用转成子类类型。
3、注意:
A、不能将父类对象转成子类类型。
B、只有当父类引用指向自己的子类对象时,才可以转型。
C、多态自始至终都是子类对象在做着变化。
4、 instanceof 的应用:
A、java 中的 instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。
instanceof 通过返回一个布尔值,来指出这个对象是否是这个特定类或者是它的子类的一个实例。(来自网络释义)
B、 instanceof 用于判断的两种情况:
①子类类型是有限的(比如:人分为男人的女人);
②当所传的类型需进行其他操作(比如比较的时候,需确定子类的类型来调用对应的方法)。
示例(接上例):public static void main(String[] args) { Animal c = new Cat();//类型提升:向上转型;猫类型提升为动物类型。 function(c); Cat c1 = (Cat)c;//向下转型:动物类型转型为猫类型。 c1.catchMouse(); //不可以将父类对象转成子类类型 //Animal a = new Animal(); //Cat c = (Cat)a; } public static void function(Animal a)//Animal a = new Dog(); { a.eat(); //Cat c = (Cat)a;//如果传进来的是狗,编译失败。 //c.catchMouse(); //修正后代码 if (a instanceof Cat) { Cat c = (Cat)a; c.catchMouse(); } else if (a instanceof Dog) { Dog d = (Dog)a; d.kanJia(); } else { System.out.println("未知动物类型"); } }
四、面向对象——多态——示例
需求:
基础班学生:
学习,睡觉。
高级班学生:
学习,睡觉。
但是基础班和高级班的学习内容和睡觉方式可能不一样。
可以将这两类事物进行抽取。
代码:
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 DuoTaiDemo { public static void main(String[] args) //主函数是最终的调用者,由主函数调用工具类,让工具类去完成对应的功能。 { DoStudent ds = new DoStudent();//建立功能对象 ds.doSome(new BaseStudent());//调用功能对象的方法 ds.doSome(new AdvStudent()); } } 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"); } }
总结:多态将对象调用的事情变简单了。从指挥一个对象做事情变成指挥一批对象做事情,那是因为找到了这些对象的共同所属类型。
=====主函数一般作为最终调用者,也就是客户端;并建立好工具类,让工具类去完成相应的调用动作。五、面向对象——多态中成员的特点
1、在多态中,非静态成员函数的特点:
在编译时期:编译能否通过,请参阅引用型变量所属的类中是否有调用的方法;
在运行时期:运行是否OK,请参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看等号左边,运行看等号右边。
2、在多态中,成员变量的特点:
无论编译和运行,都参考等号左边(引用型变量所属的类)。
3、在多态中,静态成员函数和特点:
无论编译和运行,都参考等号左边。
示例:class Fu { 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 { 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 DuoTaiDemo { public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.num);//结果是5 Zi z = new Zi(); System.out.println(z.num);//结果是8 f.method1(); //zi method_1 f.method2(); //fu method_2 //f.method3();//编译失败:因为父类中没有该方法 f.method4();//fu method_4 z.method4();//zi method_4 } }
六、面向对象——多态的主板示例
需求:
电脑运行实例:电脑运行基于主板。
代码体现:class DuoTaiDemo { public static void main(String[] args) { MainBoard mb = new MainBoard(); mb.run(); mb.usePCI(null); mb.usePCI(new NetCard()); mb.usePCI(new SoundCard()); } } class MainBoard { public void run() { System.out.println("mainboard run "); } public void usePCI(PCI p)//PCI p = new NetCard()//接口型引用指向自己的子类对象。//多态的应用 { if(p!=null) { p.open(); p.close(); } } } interface PCI //父类 { public void open(); public 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"); } }
七、面向对象——多态的扩展示例
需求:数据库的操作。
数据是:用户信息。
1,连接数据库。JDBC Hibernate
2,操作数据库。
c create r read u update d delete
3,关闭数据库连接。
代码体现:class DBOperate { public static void main(String[] args) { UserInfoDao ui = new UserInfoByHibernate();//多态的应用 ui.add(user); ui.delete(user); } } 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,关闭连接; } }
八、面向对象——Object类——equals()
Object 类层次的根类,所有对象的直接或者间接父类。该类中定义的是所有对象都具备的功能。
Object 类中的 equals(Object obj)方法比较的是两个对象的内存地址值。
也就相当于 == 。
示例:class Demo { } class Object { public static void main(String[] args) { Demo d1 = new Demo(); Demo d2 = new Demo(); Demo d3 = d1; sop(d1.equals(d2));//false sop(d1.equals(d3));//true sop(d1==d2);//false sop(d1==d3);//true } }
但实际开发中比较两个对象的内存地址值是没有意义的,所以需要复写equals方法。
例如:class ObjectDemo { public static void main(String[] args) { Demo d1 = new Demo(4); Demo d2 = new Demo(5); System.out.println(d1.equals(d2)); Person p1 = new Person(); System.out.println(d1.equals(p1)); } } class Demo //extends Object { private int num; Demo(int num) { //super(); this.num = num; } public boolean equals(Object obj) { //复写Object类中的equals方法 if(!(obj instanceof Demo)) //判断 return false; Demo d = (Demo)obj; //向下转型 return this.num == d.num; } } class Person { }
九、面向对象——Object类——toString()
toString()方法分解:
getClass().getName()+"@"+Integer.toHexString(hashCode())
代码分析:class ObjectDemo { public static void main(String[] args) { Demo d1 = new Demo(); Class c = d1.getClass(); System.out.println(d1.toString()); //Demo@15db9742 System.out.println(d1.getClass().getName()); //Demo System.out.println(d1.hashCode()); //366712642 //十进制 System.out.println(Integer.toHexString(d1.hashCode())); //15db9742 //十六进制 } } class Demo { }