此篇文章来自一个初学Java不久的学生,内容的用词、深度、广度甚至部分理解不够到位,再加上Markdown语法的不熟练,所以排版不够美观。但还是希望有疑问的读者能够读完全文,大家遇到问题可以一起交流。谢谢!
多态,顾名思义一种东西的多种形态。那面向对象里面为什么或者说哪里来的多态?要想顺理的理解多态,就需要你对封装和继承又很好的理解。内容可以参考我之前写的 面向对象三大特性之——封装 面向对象三大特性之——继承。 当然,也希望你读完这篇文章之后,能够完成下面几个问题。 1.什么是多态,为什么使用多态? 2.理解为什么会有抽象类和接口,二者的区别是什么? 3.理解使用多态类和几口实现多态的不同。
1.什么是多态?
答:同一个对象,在不同时刻表现出来的不同形态,在继承的子父类里面体现。
2.多态的前提?
答:
1)要有继承或实现关系
2)要有方法的重写
3)要有父类引用指向子类对象
成员变量:编译看父类,运行看父类(编译看左边,运行也看左边)
成员方法:编译看父类,运行看子类(编译看左边,运行看右边)
People类(父类):
public class People { int age = 100; public void show() { int age = 200; System.out.println("年龄是:"+age); } }Student类(子类):
public class Student extends People { int age = 10; @Override public void show() { int age = 20; System.out.println("年龄是:"+age); } public void study() { System.out.println("要好好学习"); } }测试类:
public class Demo01 { public static void main(String[] args) { People p = new Student(); p.show(); } }运行结果:
年龄是:20
总结:成员方法在编译的时候查看父类里面是否含有show()方法,如果有,在运行的时候在子类里面查找show()方法,然后执行子类方法的代码。由于子类继承了父类,所以只要父类能够查找到指定的方法,子类的方法里面就一定含有重写父类的方法。所以运行代码,产出结果。
优点:提高程序的扩展性。定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作
缺点:不能使用子类的特有成员
为什么会出现自动转型?
举个例子,我想要打印子类的成员变量age。但是根据多态成员的访问特点来看。成员变量编译看左边,执行也看左边,根本没有出现右边(子类)的成员变量。于是多态的转型就出来了。
1.向上转型:也成为自动转型,即正常的运行方式
2.向下转型:称为强制转型。
主要就是这段代码的理解:
int age = ((Student) p).age; System.out.println(age);p被声明为People类型,此时需要向下转型为People的子类Student类型。如果你能想到整型数据的强制转化,这里运用了相同的语法格式。(Student)p。那么此时的p则是Student类型的,然后再调用它里面的age对象,再赋值给main方法里面定义的变量age,打印输出。
当我们在做子类相同功能进行抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了。在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。口水话理解就是:抽象类就相当于一个没有劳动能力的父亲,但是心中却又有很多抱负(成员变量和常量),于是只能将自己的想法定义为抽象类,自己没有办法实现,之能把这些想法告诉自己的子类,让它们帮助自己去实现这些抱负(常量和方法)
1.抽象类和抽象方法必须使用 abstract 关键字修饰
//抽象类的定义 public abstract class 类名 {} //抽象方法的定义 public abstract void eat();2.抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
3.抽象类不能实例化,要想实现抽象类的方法,需要借助其子类实现,也就是多态的概念。
4.抽象类的子类可以是一下两种情况
1)要么重写抽象类中的所有抽象方法
2)要么是抽象类
成员变量:既可以是变量,也可以是常量
构造方法:空参构造,有参构造
成员方法:抽象方法,普通方法
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。Java中的接口更多的体现在对行为的抽象。这个在我们现实中的理解就好比,在离开继承的is…a关系之后,自然界还有一种关系就好比,你和老鹰会飞,飞机也会飞,你做梦的时候也会飞,但是你们三者很难找到一个继承的关系,所以接口就来了,它就类似于一个功能的开关。当给你连接这个接口的时候,你就可以获得这个功能。
接口用关键字interface修饰
public interface 接口名 {}类实现接口用implements表示
public class 类名 implements 接口名 {}接口不能实例化:这一点和抽象类的用法相同。要想实现接口的方法,需要借助其子类实现,也就是多态的概念。
接口的子类:要么重写接口中的所有抽象方法,要么子类也是抽象类
成员变量:只能是常量 默认修饰符:public static final
构造方法:没有,因为接口主要是扩展功能的,而没有具体存在
成员方法:只能是抽象方法
默认修饰符:public abstract
需求:定义一个抽象的Father类,定义一个Son类用来充当Father的子类,并且实现Father的抽象方法。在测试类里面,利用多态的方式,调用Son里面指定的方法
定义一个Father类:
public abstract class Father { public abstract void hobby(); }定义一个Son类:
public class Son extends Father { @Override public void hobby() { System.out.println("我的爱好是打篮球"); } }定义一个测试类:
public class Demo03 { public static void main(String[] args) { Father f = new Son(); f.hobby(); } }代码执行结果:
我的爱好是打篮球需求: 定义一个Fly的接口,里面包含两个不同定义方式的eat和fly方法。再定义三个方法People、Plane和Eagles用于实现接口。定义一个测试类,用前面提到的不同的方式去调用不同的方法和常量。
定义一个Fly的接口类:
public interface Fly { //省略了默认的修饰符的方式定义方法 void fly(); //加上默认的修饰符的方式定义方法,除方法名不一样外,两者的效果一样 public abstract void eat(); }定义三个Fly接口的实现类,People、Plane和Eagles:
People类:
public class People02 implements Fly{ int num =1; //在子类中对接口中的方法进行重写 @Override public void eat() { System.out.println("我是人,我要吃饭"); } //在子类中对接口中的方法进行重写 @Override public void fly() { System.out.println("我是人,我做梦会飞"); } }Plane类:
public class Plane implements Fly { int num = 2; @Override public void eat() { System.out.println("我是飞机,我不需要吃饭"); } @Override public void fly() { System.out.println("我是飞机,我可以飞的很高"); } }Eagles类:
public class Eagles implements Fly { int num =3; @Override public void eat() { System.out.println("我是老鹰,我要吃蛇"); } @Override public void fly() { System.out.println("我是老鹰,我会飞翔"); } }定义一个测试类:
public class Demo02 { public static void main(String[] args) { //利用多态的方式创建一个对象 Fly f = new People02(); f.eat(); f.fly(); //向下转型的运用 System.out.println(((People02) f).num); //正常的实例化Plane Plane p = new Plane(); p.eat(); p.fly(); System.out.println(()); Fly e = new Eagles(); //使用的是向下转型的方式调用这个方法,但是成员方法的访问特点是:编译看左边,执行看右边,所以使用下面的方式调用也可以 ((Eagles)e).eat(); e.fly(); //利用向下转型(强制转型)的方式,打印输出其实现子类的成员变量 System.out.println(((Eagles) e).num); } }代码执行结果:
我是人,我要吃饭 我是人,我做梦会飞 1 我是飞机,我不需要吃饭 我是飞机,我可以飞的很高 2 我是老鹰,我要吃蛇 我是老鹰,我会飞翔 3