黑马程序员_Java基础Day08_面向对象之多态(Done)

来源:互联网 发布:linux qt libusb 编辑:程序博客网 时间:2024/05/16 18:10

------- android培训、java培训、期待与您交流! ----------


开始接触面向对象最后一个特征——多态。


多态可以理解为事物存在的多种体现形态。
如:对于猫、狗...等,既能称他们为猫、狗...也可以叫它们动物;对于冰箱、洗衣机...等,既能称他们是冰箱、洗衣机...也可以叫它们家电。即:

洗衣机 x = new 洗衣机();家电 x = new 洗衣机();

上面这个伪代码是Java中对象的多态性的体现。其实,函数的重载和覆盖也是多态性的表现形式。我们这里主要讨论的是对象上的多态性。


多态的体现:父类的引用指向了自己的子类对象。父类的引用也可以接收自己的子类对象。

多态的前提:必须是类与类之间有关系,要么继承(父类),要么实现(接口)。通常还需要存在覆盖,否则没有意义。

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

多态的弊端:提高了代码的扩展性,但是只能使用父类的引用使用父类中的成员(变量,方法)。

abstract class Animal//定义抽象类,所有的动物都有吃的功能,但是具体吃什么不确定,抽象出来。{abstract void eat();}class Cat extends Animal//定义Cat类继承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方法调用对应Animal的eat()方法function(d);function(p);}public static void function(Animal a)//定义一个功能,接收Animal类型的引用,调用其eat()方法{a.eat();}//可以看到,日后如果又有了新的需求,需要定义一个新的动物,只需使用 Animal x = new 新动物(); 的方式创建对象,直接调用eat()方法即可,极大的提高了程序的扩展性。 }
运行结果如下:

如果我们需要使用子类的特有功能时应该怎么做呢?这时就涉及到了“转型”。
在数据类型中,我们有:

byte b = 2;int x = b;
这里就将b向上转型成了int型。这里可以与此类比。
class Animal{eat();}class Cat extends Animal{eat(); catchMouse()}Animal a = new Cat();Cat c = (Cat)a;//父类引用强制转换成子类类型c.catchMouse();//调用子类特有功能//*****而如果是下面这样就是错误的*****Animal a = new Animal();Cat c = (Cat)a;//a是父类对象,不可以强制转换

向上转型是自动完成的,而向下转型必须强制类型转换

class Animal{}class Cat extends Animal{}//猫继承动物Animal a = new Cat();//父类引用指向子类对象,多态体现Cat c = (Cat)a;//将父类的引用强制转型为子类类型


多态中成员函数的特点:
在编译时期:参阅引用所属的类中是否有调用的方法。如果有,编译通过;如果没有,编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
一言蔽之,即:成员函数在多态中调用时,编译看左边,运行看右边。

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

多态中静态成员函数的特点:
无论编译还是运行,都参考左边(静态绑定)。

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  DuoTaiDemo4{public static void main(String[] args) {Fu f = new Zi();//父类引用指向子类对象f.method1();//zi method_1f.method2();//fu metho//f.method3();//会编译出错,因为父类中没有定义method3()方法f.method4();//fu method_4System.out.println(f.num);//5成员变量,参考左边}}

运行结果:

//小练习:定义一台电脑,能够通过USB接口,扩展其功能。

interface USB{public abstract void run();public abstract void interrupt();}class Computer{public void run(){System.out.println("电脑开启");}public void useUSB(USB u){if (u==null)System.out.println("还没有使用USB设备");else{u.run();u.interrupt();}}}class Mouse implements USB{public void run(){System.out.println("鼠标已经连接");}public void interrupt(){System.out.println("鼠标断开");}}class Phone implements USB{public void run(){System.out.println("手机已经链接");}public void interrupt(){System.out.println("手机断开");}}class DuoTaiDemo5 {public static void main(String[] args) {Computer c = new Computer();c.run();c.useUSB(null);c.useUSB(new Phone());c.useUSB(new Mouse());}}
运行结果:


Object类

Object类是所有类的直接或者间接父类,该类中定义的是所有的对象都具备的功能。

Java认为,所有的对象都具有比较性,都能够比较两个对象是否相同。这个比较的方法就是equals方法。在方法定义之初,并不知道具体要对哪两个对象进行比较,为了提高扩展性equals方法的形式参数采用的是Object类型的对象,这就是多态性的体现。另一方面,如果子类中也有类似比较的功能,则没有必要重新定义,只需继承equals方法,复写其功能即可,这是覆盖的体现。

注意:在Object中,equals方法源代码是:

public boolean equals(Object obj) {        return (this == obj);    }
可见,equals比较的是对象的引用,即他们的内存地址值,也就是比较是不是同一个对象。


原创粉丝点击