您的位置:首页 > 职场人生

黑马程序员_<<面向对象(多态)---03>>

2013-10-23 23:17 489 查看
---------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------

1.多态

1. 概述

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

因为有的继承,所以有了父类和子类关系,那么就提现出来了多态的特性。

当一类事物之间肯定有存在某种关系,例如儿子和父亲,学生和人,工人和人,那么他们也有共性,那么当我们划分的越细,那么子类就越多,那么我们调用相同特性的时候,就会比较麻烦,那么我们就使用父类来接受子类的对象,这样就可以调用相同的特性方法。

例如:

动物:狗,猪,兔子…等,他们都有吃的行为。

interface Animal {
void eat();
}
public class Dog implements Animal {
/*重写父类的方法*/
public void eat() {
System.out.println("狗吃骨头");
}
}
public class Pink implements Animal {

/* 重写父类的方法 */
public void eat() {
System.out.println("猪吃猪饲料");
}

}
public class DuoTaiDemo {
public static void main(String[] agrs) {
animalEat(new Dog());
animalEat(new Pink());
}

/**
* 用父类来接受子类,那么就可以调用子类和父类相同的方法
*/
public static void animalEat(Animal animal) {
animal.eat();
}
}
结果:
狗吃骨头
猪吃猪饲料


从结果可以看出,父类可以接受子类对象,相当于 Animal animal=new Dog();

结论:父类的引用指向了自己的子类对象。

父类的引用也可以接受自己的子类对象。

2. 多态的特点

要想使用多态,那么前提是:类与类之间必须有关系,存在覆盖。

多态的好处:提高了程序的扩展性,也可以减少代码。

多态的弊端:只能使用父类的引用访问子类和父类共有的方法。

3. 多态的应用

使用:可以使用父类对象作为参数接受子类对象。

向上转型:子类类型转换成父类类型。

向下转型:强制把父类的引用转换成子类类型。

Instanceof:判断是否是此类型 子类是有限的,或者是对某一特殊类型进行转换。

也可以重写基类的方法,然后把共有的方法封装到一个新的类中,这样使用就更方便了。

interface Animal {
void eat();
}
public class Dog implements Animal {
/* 重写父类的方法 */
public void eat() {
System.out.println("狗吃骨头");
}

/* 自独有的方法 */
public void seeDoor() {
System.out.println("看门");
}

}
public class Pink implements Animal {

/* 重写父类的方法 */
public void eat() {
System.out.println("猪吃猪饲料");
}
/* 自独有的方法 */
public void DongDi() {
System.out.println("猪,gongdi");
}

}
public class DuoTaiDemo {
public static void main(String[] agrs) {
animalEat(new Dog());
animalEat(new Pink());
}

/**
* 用父类来接受子类,那么就可以调用子类和父类相同的方法
*/
public static void animalEat(Animal animal) {
animal.eat();
/*instanceof 是判断是否是此类对象,十寸与此类存在某种关系
* 一般情况下,只有在子类比较少的情况下,才使用此比较的方式,
* 父类不能调用子类自己独有的方法,必须强制转换成子类对象*/
if(animal  instanceof Dog){
Dog dog=(Dog)animal;
dog.seeDoor();
}else if(animal instanceof Pink){
Pink p=(Pink)animal;
p.DongDi();
}
}
}
结果;
狗吃骨头
看门
猪吃猪饲料
猪,gongdi


4. 覆盖问题

多态中成员函数的特点:

在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。

在运行时期:参阅对象所属的类中是否有调用的方法,。

简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

当父类和子类相同的成员变量,或者有相同的静态方法,那么父类接受子类对象的时候,那么调用相同的成员变量或者是相同的静态方法,那么就执行父类的, 因为,当父类和子类一加载的时候,那么其都在内存中生成,所以当然会调用弗雷德。

如果不是静态的方法那么会调用子类重写的方法。

public class Fu {
public int num=5;
/*静态成员*/
public static void show(){
System.out.println("父类的静态的show()方法");
}
public void print(){
System.out.println("父类的非静态的print()方法");
}
}
public class Zi extends Fu {
public int num=10;

public static void show(){
System.out.println("子类的静态的show()方法");
}
public void print(){
System.out.println("子类的非静态的print()方法");
}
public static void main(String[] agrs) {
Fu fz = new Zi();
fz.show();//父类的,因为是静态的方法
System.out.println(fz.num);//父类的,因为是常量
fz.print();//子类的,因为不是静态的
}
}
结果:
父类的静态的show()方法
5
子类的非静态的print()方法


2. 示例

模拟电脑的主板和PCI功能。主板中封装了PCI,其他的网卡,声卡都实现PCI接口,不管是以后扩展什么,那么继承PCI就可以在主板上上运行。

/*PCI接口*/
interface PCI {
void open();
void close();
}
/*主板*/
class MainCard {
public void run() {
System.out.println("main cardrun");
}

public void userPCI(PCI pci) {
if (pci != null) {// 加入PCI上不为空,
pci.open();
pci.close();
}
}
}

/* 网卡 */
class NetCard implements PCI {

@Override
public void close() {
System.out.println("NetCard open");
}

@Override
public void open() {
System.out.println("NetCardclose");
}

}

/* 声卡 */
class SoundCard implements PCI {

@Override
public void close() {
System.out.println("SoundCardopen");
}

@Override
public void open() {
System.out.println("SoundCardclose");
}

}

public class TextDemo {
public static void main(String[] args) {
MainCard card = new MainCard();
card.run();
card.userPCI(new NetCard());
card.userPCI(new SoundCard());
}

}
结果:
main card run
NetCard close
NetCard open
SoundCard close
SoundCard open


---------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: