多态:某一事物在不同时刻表现出来的不同状态。例如:水有液态,固态和气态等。
多态的前提:
1、要有继承关系
2、要有方法的重写,没有重写意义不大。
3、要有父类的引用指向子类的对象:父类名 f =new 子类名(。。。);
多态访问成员的特点:
1、成员变量 编译看左,运行看左
2、构造方法 创建子类对象的时候,先访问父类中的构造方法,对父类的数据先进行初始化 3、成员方法 编译看左,运行看右。 因为成员方法存在重写,所以访问看右边
4、静态成员方法 编译看左,运行也看左。 由于被static修饰的成员都是与类相关的,这里不是重写,所以运行的时候,访问的还是左边的。
多态的弊端1:多态无法访问父类中的方法名一样的方法
解决办法:不使用多态
弊端2:多态无法访问子类中特有的方法
解决办法:向下转型,类似于强制类型转换
格式:子类类名 变量名 = (子类类名)父类的引用;
对象之间的转型问题:
向上转型:Fu f = new Son();这其实就是多态的格式
向下转型:Son s = (Son)f;该转型要求转型的类与父类引用存在继承关系,并且一开始创建多态的时候,使用的是该类。
猫狗案例:
class Animal{ public void eat(){ System.out.println("吃东西"); } } class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼");; } public void run(){ System.out.println("猫抓老鼠"); } } class Dog extends Animal{ @Override public void eat() { System.out.println("狗吃骨头"); } public void look(){ System.out.println("狗看家"); } } public class Test1 { public static void main(String[] args) { Animal a=new Cat(); a.eat(); // 这里无法执行a.run(),因为多态无法访问子类的特有方法,需要向下转型: Cat c=(Cat)a;//向下转型 c.eat(); c.run(); Animal a2=new Dog(); a2.eat();//这里同上无法执行a2.look(),需要向下转型才可以执行 Dog d=(Dog)a2; d.eat(); d.look(); } }
抽象:将一个不具体的功能叫做抽象方法,如果一个类中有抽象方法,就把这个类称之为抽象类。
抽象类的特点:
1、抽象类和抽象方法都需要一个关键字来修饰:abstract
修饰一个类,放在class前面,例:abstract class Animal{};
修饰一个方法,一般放在权限修饰符后面:
定义一个抽象的show方法:public abstract void show();
2、有抽象方法的类一定是抽象类,但是抽象类不一定有抽象方法,具体的类不能有抽象方法,抽象类中可以存在抽象方法,也可以存在有方法体的方法。
3、抽象类不能被实例化,如何调用:
通过多态的形式,使用具体的子类去实例化调用方法,专业术语为:抽象多态
4、如果继承抽象类的是一个具体子类,需要重写该抽象类中所有的抽象方法;如果继承抽象类的也是一个抽象类,可以不去重写父类中的方法,也可以选择性的去重写。
abstract class Animal{ public abstract void eat(); public abstract void drink(); // 注意:抽象方法没有方法体{},连大括号都没有,直接以分号结尾 // Java抽象方法不能有主体 } class Dog extends Animal{ @Override public void eat(){ System.out.println("狗吃肉"); } public void drink(){ System.out.println("狗喝水"); } } //选择性重写抽象方法 abstract class Demo{ public abstract void fun(); public abstract void fun2(); } abstract class Demo2 extends Demo{ public void fun(){ System.put.println("抽象类Demo2重写了fun方法"); } } public class AbstractDemo1 { public static void main(String[] args) { //利用具体子类多态形式创建对象 //抽象多态的形式 Animal3 a = new Dog3(); a.eat(); a.drink(); } }
抽象类的成员特点:
成员变量:既可以是变量,也可以是常量
构造方法:可以存在构造方法,但是抽象类不能被实例化,这里的构造方法方法理论上说没有意义,但实际上构造方法在这里提供了一个在继承中初始化父类的作用。
成员方法:可以是抽象方法,但是具体的子类必须要重写该方法;也可以不是抽象方法,提高代码的复用性。
abstract class Animal{ int a=20; int b=100; Animal(){ System.out.println("这是Animal中无参构造方法"); } public abstract void eat(); public abstract void show(){ System.out.println("父类中不是抽象方法的show"); } } class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } } public class AbstractDemo2 { public static void main(String[] args) { Animal4 a = new Cat4(); System.out.println(a.a); System.out.println(a.b); a.eat(); a.show(); } }
抽象类中可以存在哪些关键字?
abstract关键字不能和哪些关键字共存?
private; static; final;