Day11 Java 多态、抽象

30 篇文章 0 订阅

多态:某一事物在不同时刻表现出来的不同状态。例如:水有液态,固态和气态等。

多态的前提:

1、要有继承关系

2、要有方法的重写,没有重写意义不大。

3、要有父类的引用指向子类的对象:父类名 f =new 子类名(。。。);

多态访问成员的特点:

1、成员变量 编译看左,运行看左

2、构造方法 创建子类对象的时候,先访问父类中的构造方法,对父类的数据先进行初始化

3、成员方法 编译看左,运行看右。 因为成员方法存在重写,所以访问看右边

4、静态成员方法 编译看左,运行也看左。 由于被static修饰的成员都是与类相关的,这里不是重写,所以运行的时候,访问的还是左边的。

编译看左是查看抽象父类中有没有该变量或者方法,有则编译不出错,否则报错。

多态的好处:

1、多态可以使代码的扩展性很好,这是由继承保证的。

2、多态可以使代码的维护性很好,这是由多态保证的。

多态的弊端1:多态无法访问父类中的方法名一样的方法

解决办法:不使用多态

弊端2:多态无法访问子类中特有的方法

解决办法:向下转型,类似于强制类型转换

格式:子类类名 变量名 = (子类类名)父类的引用;

对象之间的转型问题:

向上转型:Fu f = new Son();这其实就是多态的格式

向下转型:Son s = (Son)f;该转型要求转型的类与父类引用存在继承关系,并且一开始创建多态的时候,使用的是该类。

猫狗案例通过向下转型解决弊端2:

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();
//    编译看左,运行看右,父类中有eat方法,所以可以调用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 class Teacher{
    private String name;
    private int age;

     public Teacher() {
     }

     public Teacher(String name, int age) {
         this.name = name;
         this.age = age;
     }

     public String getName() {
         return name;
     }

     public void setName(String name) {
         this.name = name;
     }

     public int getAge() {
         return age;
     }

     public void setAge(int age) {
         this.age = age;
     }
     public abstract void teach();
 }
 class Five extends Teacher{

     public Five() {
     }

     public Five(String name, int age) {
         super(name, age);
         System.out.println("五年级班主任为:"+name);
     }

     @Override
     public void teach() {
         System.out.println("五年级在上英语");
     }
 }
 class Six extends Teacher{
     public Six() {
     }

     public Six(String name, int age) {
         super(name, age);
         System.out.println("六年级的班主任为:"+name);
     }

     @Override
     public void teach() {
         System.out.println("六年级在上语文");
     }
 }
public class Test3 {
    public static void main(String[] args) {
        Teacher t=new Five("小刘",20);
        t.teach();
        Teacher t2=new Six("小王",56);
        t2.teach();
    }
}

 抽象类中可以存在哪些关键字?

abstract可以和public共存,例如:public abstract void show();

abstract关键字不能和哪些关键字共存?

private和abstract关键字冲突

 private abstract void show2(); // java: 非法的修饰符组合: abstract和private

static和abstract关键字冲突

static abstract void show3(); // java: 非法的修饰符组合: abstract和static

final和abstract关键字冲突

 final abstract void show4(); // java: 非法的修饰符组合: abstract和final

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值