Day10-1.多态 、抽象类

1 多态

  1. 概念:事物的多种状态
    对象的多态性:
           一个对象可以使用不同的类型来表示,一个对象可以使用不同类型的引用来接收
    类型的多态性:
            一个类型可以使用不同的子类对象实现,一个类型的引用可以接收不同的子类对象
  2. 实现多态的前提:
    (1)两个类之间需要有子父类的继承关系(接口和实现类之间的实现关系)
    (2)必须使用父类的引用接收子类的对象(接口的引用接收实现类的对象)
  3. 目的:
    为了方法的重写, 提高代码的扩展性

1.1 多态中访问成员变量的特点

  1. 特点:
    编译看左边(父类),运行看左边(父类)
  2. 说明:
    (1)多态的对象名,访问一个变量,在编译的时候,先看=左边类型中有没有该变量的 定义,如果有编译成功,可以使用。
    (2)运行的时候,看=左边类型中该边浪如何赋值,父类中如何赋值,就如何使用

代码

package demos1;

public class Demo02 {
    public static void main(String[] args) {
        
        Animal a = new Cat();
        //编译看父类,有定义,可以使用
        //运行看父类:动物类
        System.out.println(a.name);
        //运行看父类:3
        System.out.println(a.age);
        //编译报错:编译看父类,父类中没有定义不能使用
//        System.out.println(a.color);
    }
}

1.2 多态中访问成员方法的特点

  1. 特点:
    编译看左边(父类),运行看右边(子类)
  2. 说明:
    (1)编译的时候看=左边的父 类中,有没有该方法的定义,如果有就可以使用
    (2)运行的时候看=右边的子类中,该方法如何实现的,子类如何实现就如何执行

代码

package demos1_poly.demo1;

public class Demo03 {
    public static void main(String[] args) {
        //多态定义:父类引用指向子类对象
        Animal a = new Cat();
        //编译看父类,有定义可以使用
        //运行看子类:子类如何实现,就如何使用
        a.print();
        a.eat();
        //编译失败:父类中没有定义,不能使用
//        a.catchMouse();
    }
}

1.3 多态中访问静态方法的特点

  1. 特点:
    编译看左边(父类),运行看左边(父类)
  2. 注意:
    多态中访问静态方法,父类的引用调用,就执行父类中定义的实现内容
    静态方法可以被子类继承,但是不能被子类重写

1.4 超人案例

1.4.1 向上向下转型

  1. 向上转型:
    使用父类的引用接收(指向)子类的对象
    特点:
    不管是访问属性还是访问方法,都需要编译看父类
    如果属性和方法在父类中有定义,才可以使用,没有定义不能使用
    缺点:降低了对象的访问范围
  2. 向下转型:
    将指向子类对象的父类引用,恢复为子类的引用
    子类类型 子类对象 = (子类类型)对象名;
    特点:恢复了子类对象访问范围
  3. 总结:
    (1)如果接收子类对象的引用是父类类型,该引用的访问范围和super关键字相同, 指向子类对象中的父类对象。
    (2)如果使用指向子类对象的父类引用访问方法,根据动态绑定机制,去子类中寻找 该方法的实现方式。
    (3)向下转型之后,虽然两个变量中存储的是同一个地址,引用访问的范围和this一样,根据就近原则访问数据。

代码

package demos1_poly.demo2;

public class Demo01 {

    public static void main(String[] args) {
        //向上转型
        //只能访问父类中定义的内容
        Man m = new SuperMan();
        System.out.println(m.name);//Mike
        m.talkBunisess();
//        m.fly();  因为多态变量表示,只能使用父类定义的,不能使用子类特有的
        //向下转型
        //恢复了对象本身的访问范围
        SuperMan sman = (SuperMan)m;
        //可以访问子类特殊的方法
        sman.fly();
        System.out.println(sman.name);
    }
}
class Man{
    String name = "Mike";
    public void talkBunisess(){
        System.out.println("谈一个几个亿的小生意!!!");
    }
}
class SuperMan extends Man{
    String name = "superMan";
    @Override
    public void talkBunisess(){
        System.out.println("谈一个几千亿的大生意!!!");
    }
    public void fly(){
        System.out.println("飞着去救人");
    }
}

1.5 instanceof关键字

  1. 格式:
    引用 instanceof 类型
  2. 特点:
    判断左边的引用是否是属于右边的类型对象
    如果是结果为真,如果不是结果为假
  3. 作用:
    在向下转型的时候,先判断该引用是否属于某一个类型,如果属于,就强转,否则不强转

代码

package demos1_poly.demo3;

public class Demo {
    public static void main(String[] args) {

        useAnimal(new Cat());
        useAnimal(new Dog());
    }

    public static void useAnimal(Animal a){// Animal a = new Dog()   Cat c = new Dog()
        a.show();

        //判断a引用是否属于毛猫类
        //属于猫类,结果为真
        if(a instanceof Cat){
            //将引用转为向下转为猫类
            //执行猫类的特殊方法
            Cat c = (Cat)a;
            c.catchMouse();
        }
        //判断a引用是否属于狗类
        //属于猫狗类,结果为真
        if(a instanceof Dog){
            //将引用向下转为狗类
            //执行狗类的方法
            Dog d = (Dog)a;
            d.lookHouse();
        }
    }
}

1.6 多态的好处

package demos1_poly.demo4;

public class Demo {
    public static void main(String[] args) {

        JuiceMachine jm = new JuiceMachine();
        jm.makeJuice(new Apple());
        jm.makeJuice(new Orange());
        jm.makeJuice(new WaterMelan());
    }
}
class JuiceMachine{
    //在方法的形参列表中,定义一个父类的类型引用
    //将来可以传递任何子类的对象(多态接收)
    //将来可以根据传递的子类对象,执行子类方法的实现内容
    public void makeJuice(Fruit f){//Fruit f = new Apple();  Fruit f = new Orange();
        f.flow();
    }
}

class Fruit{
    public void flow(){
        
    }
}
class Apple extends Fruit{
    public void flow(){
        System.out.println("流出苹果汁");
    }
}
class Orange extends Fruit{
    public void flow(){
        System.out.println("流出橘子汁");
    }
}
class WaterMelan extends Fruit{
    public void flow(){
        System.out.println("流出西瓜汁");
    }
}

2 抽象类

2.1 抽象方法

  1. 概念:将每一个子类中方法的相同部分进行一个提取,只有声明相同,只定义方法的声 明,没有实现内容。只有声明没有实现内容的方法就是一个抽象方法。
  2. 为了表示该方法是一个抽象方法,使用一个关键字:abstract 修饰方法
  3. 抽象方法不能在普通类中定义,只能在抽象类中定义,只能将类型也通过关键字abstract 修饰

2.2 抽象类特点

  1. 抽象类使用关键字:abstract修饰
  2. 抽象类和抽象方法的关系:
    抽象方法只能在抽象类中定义
    抽象类中可以没有抽象方法
  3. 抽象类不能实例化(不能创建对象)
  4. 抽象类的子类有不同的两条分支:
    如果子类继承抽象类之后,重写了父类的每一个抽象方法,那么子类就是一个普通类
    如果子类继承抽象类之后,没有重写完父类中的抽象方法,子类只能定义为一个抽象类
  5. 即使类型变为一个抽象类,要使用该类型,也需要先编译为一个字节码文件后运行

2.3 抽象类成员特点

  1. 抽象类可以定义变量(属性),不能被抽象
  2. 抽象类中可以定义普通的成员方法,也可以定义抽象的方法
  3. 抽象类中需要定义构造方法吗?
    需要。

一个类型是否需要定义构造方法,跟当前类是否可以创建对象无关。
跟当前类是否可以定义属性有关,如果类中可以定义属性,就需要对属性初始化,就需 要定义构造方法。

2.4模板设计模式

  1. 可以将每一个子类中都相同的内容,提取到父类中定义,将每一个子类中不同的内容, 可以在父类中定义为抽象方法,用于让子类强制重写。
  2. 效果:相同的代码没有反复定义多次,而且每一个子类也有自己不同的内容执行

模板类代码

package demos2_abstract.demo3;

public abstract class HomeWork {
    public void Q1(){
        System.out.println("1、喜羊羊与灰太狼中,灰太狼的老婆叫什么?");
        System.out.println("A:红太狼   B:粉太郎   C:粉红太狼");
        System.out.println(Answer1());
    }

    public void Q2(){
        System.out.println("2、天龙八部中乔峰的大招叫什么?");
        System.out.println("A:葵花点穴手  B:打狗棒法  C:降龙十八掌");
        System.out.println(Answer2());
    }

    public abstract String Answer1();
    public abstract String Answer2();
}

子类代码

package demos2_abstract.demo3;

public class Stu1 extends HomeWork{

    @Override
    public String Answer1() {
        return "A";
    }

    @Override
    public String Answer2() {
        return "C";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值