一、多态
1、什么是多态?
①多态是同一行为具有表现出多种形态和形式的功能。
②多态是父类能够调用子类的对象。在对同一父类的不同子类传入同一消息时,子类表现出不同的行为。
以上两点结合理解。
③多态使用了继承和方法的重写。
2、多态如何使用?
场景模拟:有一个动物园,里边有狮子,鹿,丹顶鹤三种动物,三种动物都具有吃的行为,但是吃的东西不一样。饲养员要喂它们吃东西。
①实现一:不使用多态
public class Crane{ public void eat(){ System.out.println("丹顶鹤吃鱼"); } }
public class Deer{ public void eat(){ System.out.println("鹿吃草"); } }
public class Lion{ public void eat(){ System.out.println("狮子吃肉"); } }
public class Feeder { // 在方法中传入类作为参数 public void weishi(Crane crane){ System.out.println("开始喂食"); // 喂丹顶鹤 crane.eat(); } public void weishi(Deer deer){ System.out.println("开始喂食"); // 喂鹿 deer.eat(); } public void weishi(Lion lion){ System.out.println("开始喂食"); // 喂狮子 lion.eat(); } }
public class TestDemo1 { public static void main(String[] args) { // 创建饲养员类 Feeder feeder = new Feeder(); Crane crane = new Crane(); feeder.weishi(crane); Deer deer = new Deer(); feeder.weishi(deer); Lion lion = new Lion(); feeder.weishi(lion); } }
可以看到,在饲养员类中,每一个动物类都需要重载一个weishi()方法,如果动物有成千上万种,我们就需要写成千上万个weishi()方法,这样虽然功能都实现了,但是代码无比繁杂,不利于维护。
②实现二:使用多态
创建一个Animal类,各个具体动物类都继承这个类。
public class Lion extends Animal{ @Override public void eat(){ System.out.println("狮子吃肉"); } }
public class Deer extends Animal{ @Override public void eat(){ System.out.println("鹿吃草"); } }
public class Crane extends Animal{ @Override public void eat(){ System.out.println("丹顶鹤吃鱼"); } }
public class Feeder { // 在方法中传入类作为参数,此处使用Animal类作为参数 public void weishi(Animal animal){ System.out.println("开始喂食"); animal.eat(); } }
public class TestDemo1 { public static void main(String[] args) { // 创建饲养员类 Feeder feeder = new Feeder(); Animal crane = new Crane(); feeder.weishi(crane); Animal deer = new Deer(); feeder.weishi(deer); Animal lion = new Lion(); feeder.weishi(lion); } }
这里可以看到,在饲养员类中,只需要写一个方法,参数为Animal类。在测试类中,每个创建出来的具体动物对象都使用Animal类修饰。方法中虽然只传入了Animal类,但是会根据传入的具体对象,到对应的类中取调用对应的方法。这样即使有成千上万种动物,也只管创建类就行。这里就是父类可以调用子类的对象,虽然调用的方法相同,但是表现出来的形态却不同。
3、多态中涉及到向上转型和向下转型
①向上转型
Animal lion=new Lion();
向上转型是自动转型。创建的是子类对象,使用父类来修饰创建出来的对象。
缺点:使用向上转型后,子类中的独有的方法和属性就无法使用对象调用。
②向下转型
Lion lionDown=(Lion)lion;
向下转型是强制转型,慎用。不过这样就可以调用子类中独有的方法和属性了
在开发中,继承多态使用不多,主要还是下边介绍的接口多态。
二、抽象 abstract
1、什么是抽象?
①抽象类存在的目的不是创建对象,而是为了让子类继承
②抽象类中有类的行为,但是没有具体实现,具体实现是在子类中实现的
③抽象类除了不能创建对象,但是类的其他功能都不影响使用,构造方法,成员属性,成员方法的使用和普通类一样
2、抽象的格式:
①抽象类
访问修饰符 abstract class 类名{};
②抽象方法
访问修饰符 abstract 返回值 方法名();
抽象方法没有大括号,也就没有方法体。
3、使用
父类(抽象类):
public abstract class Animal { public abstract void eat(); }
子类(继承类):
子类要继承父类,要么子类是一个抽象类,要么子类中实现了父类中的抽象方法。
①子类为抽象类
public abstract class Cat extends Animal { }
②子类实现抽象方法
public class Cat extends Animal { public void eat(){ } }
抽象类中可以有普通方法:
public abstract class Animal { public abstract void eat(); public void jump(){ System.out.println("跳"); } }
4、特点
①抽象类或方法使用abstract修饰
②抽象方法必须在抽象类中,抽象方法没有方法体
③抽象类中也可以有非抽象方法
④继承抽象类的子类,要么是抽象类,要么实现了父类中的抽象方法
⑤抽象类有构造函数,但是不能new对象
三、接口
1、什么是接口?
①简单说,接口是一个特殊的抽象类。
②接口时java中的一个抽象类型,是抽象方法的集合,使用Interface声明,有特定的语法和结构
③广义上讲,接口是一个对象的方法特征的集合,是一种逻辑上的抽象。
2、接口的定义格式:
权限修饰符 Interface 接口名{};
接口中都是抽象方法,没有方法的实现。没有构造方法,不能创建对象
3、接口的使用步骤:
①创建接口
②实现接口。接口的实现类必须将接口中的抽象方法全部实现
③创建继承类的对象,进行调用
注意:如果实现类没有全部实现抽象方法,那么这个实现类自身必须是抽象类
4、接口中的内容
①常量(不可变)
[public static final] int AGE=2;
中括号中的内容可以不写,常量名全部使用大写字母。
使用:接口名.常量名
②抽象方法
[权限修饰符 abstract] 返回值 方法名();
③默认方法
假设一个接口,有一万个实现类,但是现在需要在接口写一个只有一个实现类使用的方法,如果还写抽象方法,一万个实现类必须全部 实现,明显不行,这时候就可以使用默认方法,需要就重写,不需要就不用动。
格式: 默认方法有方法体
defalut 返回值 方法名(){};
public interface BBB { public static final int AGE=0; default void sooo(){ System.out.println("接口"); } }
public class bbImpl implements BBB { @Override public void sooo() { System.out.println("接口的实现类"); } }
5、接口和类的区别
①类与类中只能单继继承
②接口和接口可以多继承,A接口继承B、C接口,可以同时具有两个接口中的抽象方法,还可以具有自己的抽象方法
③类可以实现多个接口
④接口没有构造方法