多态的基本条件
- 有继承或者实现,
- 有方法的重写
- 有父类的引用指向子类
多态的访问特点
- 成员变量:编译看左边,执行看左边
- 成员方法:编译看左边,执行看右边
多态的优点和缺点
- 优点:可以有很高的程序扩展性,具体体现,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作
- 弊端:不能使用子类的特有功能
上代码!!
public class Animal {
//定义一个成员属性
public int age=40;
//父类 动物类
public void eat(){
System.out.println("这是我们父类,动物都有吃的方法");
}
}
public class Dog extends Animal{
public int age=20;
public int weight=40;
@Override
public void eat() {
System.out.println("狗来吃饭了");
}
public void show(){
System.out.println("show 方法");
}
}
Animal animal=new Dog();//父类指向子类
animal.eat();
//System.out.println(animal.weight);在编译阶段直接报错,原因编译中需要看左边是否有我们的成员变量eat
System.out.println(animal.age);//animal有age属性 执行看左边 左边是animal所以能执行
}
}
抽象类特点
* 1、在方法上加上abstract进行修饰,则该方法是抽象方法
* 记住:如果在该类上存在一个抽象方法,则该类必须是抽象方法
* 2.在一个抽象类中可以存在多个抽象方法
* 3.在一个类中可以定义我们的非抽象方法的
* 4.子类必须要重写父类抽象中所有的抽象方法的(但是抽象类中非抽象方法没说必要重写)
* 5.如果子类没有重写父类的抽象方法,则该类也需要为抽象类,继承父类中的抽象方法
* 6.抽象类不能进行实例化的,必须通过子类来进行实例化的
* AnimalParent dog=new Dog();
* AnimalParent cat=new Dog();
* 7.在我们抽象类中不一定要有抽象方法的
* 抽象类中可以有构造函数的,可以有有参构造函数,子类访问父类初始化的时候,可以给我们的父类的成员属性进行赋值
* new出我们的子类对象 先执行我们的父类中无参构造方法 在执行子类中有参构造方法
上代码
public abstract class AnimalParent {
/**
* eat是没有方法体的,具体都是交给我们的子类重写的
* 如果在方法上加上我们abstract修饰,那么我们的方法就是抽象方法
* 如果在一个类中存在一个抽象方法,那么则该类必须是抽象类
*/
public abstract void eat();
}
//在抽象类中的抽象方法,子类是必须是要重写的
@Override
public void eat() {
System.out.println("我是猫.....俺在吃鱼");
}
}
public class Dog extends AnimalParent{
@Override
public void eat() {
System.out.println("我是狗类....我在吃骨头");
}
}
public static void main(String[] args) {
AnimalParent dog=new Dog();
AnimalParent cat=new Cat();
dog.eat();
cat.eat();
}
}
接口
- 接口的实现类是要重写接口中所有的方法的
- 接口是体现抽象的行为
- 接口是不能够进行实例化的 抽象类也不能直接实例化的
- 在接口中定义的成员变量都是常量,默认的情况下都加上final static了,可以直接通过接口名称.访问既可
- 在接口中定义的方法都是抽象方法都会默认加上(public static final)关键字进行修饰了. 实现类必须要重写接口中所有的抽象方法
- 在接口中定义非抽象方法是可以的,default关键字进行修饰 在Jdk8之前是不能定义非抽象方法的
- 在接口中是没有构造方法的,在抽象类中是有构造方法的,因为接口是对我们的行为来做抽象的概念,是没有具体的存在的
- 如果我们定义一个类,默认的情况下没有任何父类。则在默认的情况下就继承了我们Object父类
类和接口的区别
* 类和类的继承关系(一个类只能够单继承一个父类,不能够多继承N多个不同的父类)继承关系,只能单继承,但是可以多层继承
* 类和接口的实现关系。(一个类可以实现N多个不同的接口)
* 接口和接口的继承关系,(一个接口是可以额继承N多个不同的接口的)
解释一下吧!上代码!!!
//接口
public abstract void eat();
public default void show(){
System.out.println("我们在父类中定义了一个非抽象方法");
}
}
@Override
public void eat() {
System.out.println("我是猫-----喜欢吃鱼");
}
public static void main(String[] args) {
Animal animal=new Cat();
animal.eat();
}
}
还是不明白的话举了一个完整的例子
* 举:门和报警器 ,将门设为抽象类
* 行为:关门,开门,报警
* 门的品牌---美心门,盼盼门
* 盼盼门可以开门关门报警功能
* 美心门可以开门关门,但是不能报警
流程图上来一下就明白!
![](https://img2022.cnblogs.com/blog/2761772/202203/2761772-20220313152559632-1596119676.png)
public abstract class Door {
/**
* 定义两个成员属性
*/
private int height;
private int width;
private String name;
/**
* 生成有参构造方法
* @param height
* @param width
* @param name
*/
public Door(int height, int width, String name) {
this.height = height;
this.width = width;
this.name = name;
}
/**
* 生成get方法
*/
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public String getName() {
return name;
}
/**
* 定义开门的抽闲方法
*/
public abstract void open();
/**
* 定义关门的抽闲方法
*/
public abstract void close();
}
定义接口单独实现报警功能
/**
* 报警功能
*/
void alarm();
}
public class PanPanDoor extends Door implements Alarm{
/**
* 调用父类中的构造方法
*
* @param height
* @param width
* @param name
*/
public PanPanDoor(int height, int width, String name) {
super(height, width, name);
}
@Override
public void open() {
System.out.println("我是盼盼门自动指纹开门");
}
@Override
public void close() {
System.out.println("我是盼盼门可以自动指纹关门");
}
@Override
public void alarm() {
System.out.println("我是盼盼门可以有报警功能");
}
}
/**
* 调用父类构造方法
*
* @param height
* @param width
* @param name
*/
public MeiXinDoor(int height, int width, String name) {
super(height, width, name);
}
@Override
public void open() {
System.out.println("我是美心门自动指纹开门");
}
@Override
public void close() {
System.out.println("我是美心门自动指纹关门");
}
}
运行结果
![](https://img2022.cnblogs.com/blog/2761772/202203/2761772-20220313152513287-659304086.png)