面向对象 (多态)+JAVA学习笔记-DAY09

09.01 多态的概念

  • A:概念
    • 同一个对象在不同时刻体现出来的不同状态
  • B:前提
    • a: 要有继承
    • b: 要有方法重写
    • c: 要有父类引用指向子类对象
  • C:分类

    • a: 具体类多态

      class Fu {}
      class Zi extends Fu {}
      
      Fu f = new Zi();
      
    • b: 抽象类多态

      abstract class Fu {}
      class Zi extends Fu {}
      
      Fu f = new Zi();
      
    • c: 接口多态

      interface Fu {}
      class Zi implements Fu {}
      
      Fu f = new Zi();
      

09.02 多态中的成员访问特点

  • A:成员变量
    • 编译看左边(父类),运行看左边(父类)
    • 内存图
  • B:构造方法
    • 子类的构造都会默认访问父类构造
  • C:成员方法
    • 编译看左边(父类),运行看右边(子类)(动态绑定)
    • 内存图
  • D:静态方法

    • 编译看左边(父类),运行看左边(父类)
    • 静态方法与类相关,算不上重写,所以还是在左边

      class Demo_Polymorphic {
          public static void main(String[] args) {
              Father f = new Son();
              System.out.println(f.num);//10
              f.print();//Son print
              f.method();//Father static method
      
              Son s = new Son();
              System.out.println(s.num);//20
          }
      }
      
      class Father {
          int num = 10;
          public void print() {
              System.out.println("Father print");
          }
          public static void method() {
              System.out.println("Father static method");
          }
      
      }
      
      class Son extends Father {
          int num = 20;
          public void print() {
              System.out.println("Son print");
          }
          public static void method() {
              System.out.println("Father static method");
          }
      }
      

09.03 超人的故事

  • A: 案例分析

     class Test_SuperMan {
        public static void main(String[] args) {
            Person p = new SuperMan();//父类引用指向子类对象,超人提升为人,向上转型
            System.out.println(p.name);
            p.business();
            SuperMan sm = (SuperMan)p;//向下转型
            //p.fly();
            sm.fly();
        }
    }
    
    class Person {
        String name = "Join";
        public void business() {
            System.out.println("谈生意");
        }
    }
    
    class SuperMan extends Person{
        String name = "SuperMan";
        public void business() {
                System.out.println("谈几个亿的生意");
        }
    
        public void fly() {
            System.out.println("我要救人");
        }
    }
    

现象:子可以当作父使用,父不能当作子使用。

09.04 多态的向上转型和向下转型

  • A:向上转型
    从子到父
  • B:向下转型
    从父到子
  • C: 内存图

09.04 多态的好处和弊端

  • 多态的好处:
    • A:提高代码的维护性(继承体现)
    • B:提高代码的扩展性(多态体现)
  • 多态的弊端:
    • 父不能使用子的特有功能。
  • 现象:

    • 子可以当作父使用,父不能当作子使用。
      *案例演示

      class Demo_Animal {
          public static void main(String[] args) {
              method(new Cat());//Animal a = new Cat();  开发中很少在创建对象的时候用父类引用去指向子类对象,直接创建子类对象
              method(new Dog());
      
          }
          public static void method(Animal a) {
      
              //关键字:instanceof判断前边的引用是否是后边的数据类型
              if(a instanceof Cat) {
                  Cat c = (Cat)a;
                  c.eat();
                  c.catchMouse();
              }else if(a instanceof Dog) {
                  Dog d = (Dog)a;
                  d.eat();
                  d.lookhome();
              }else {
                  a.eat();
              }
          }
      }
      
      class Animal {
          public void eat() {
              System.out.println("Animal eat ");
          }
      }
      
      class Dog extends Animal{
          public void eat() {
              System.out.println("Dog eat ");
          }
          public void lookhome() {
              System.out.println("Dog lookhome ");
          }
      }
      
      class Cat extends Animal{
          public void eat() {
              System.out.println("Cat eat ");
          }
          public void catchMouse() {
              System.out.println("Cat catchMouse ");
          }
      }
      

09.05 面试题分析

/*
    看程序写结果:先判断有没有问题,如果没有,写出结果

    多态的成员访问特点:
        方法:编译看左边,运行看右边。

    继承的时候:
        子类中有和父类中一样的方法,叫重写。
        子类中没有父亲中出现过的方法,方法就被继承过来了。
*/
class DuoTaiTest {
public static void main(String[] args) {
    A a = new B();
    a.show();//爱   类A的show里的show2调用类B的show2

    B b = new C();
    b.show();//你    类B的show方法继承自A类,show方法里调用的show2为C类的show2
}
}

class A {
    public void show() {
        show2();
    }
    public void show2() {
        System.out.println("我");
    }
}
class B extends A {
    /*
    public void show() {
        show2();
    }
    */

    public void show2() {
        System.out.println("爱");
    }
}
class C extends B {
    public void show() {
        super.show();
    }
    public void show2() {
        System.out.println("你");
    }
}

09.06 抽象类的概述及其特点

  • A: 概念
    把多个共性的东西提取到一个类中,这是继承的做法。

    但是呢,这多个共性的东西,在有些时候,方法声明一样,但是方法体。
    也就是说,方法声明一样,但是每个具体的对象在具体实现的时候内容不一样。
    所以,我们在定义这些共性的方法的时候,就不能给出具体的方法体。
    而一个没有具体的方法体的方法是抽象的方法。
    在一个类中如果有抽象方法,该类必须定义为抽象类。

  • B: 抽象类的特点
    • A:抽象类和抽象方法必须用关键字abstract修饰
      • abstract class 类名{}
      • public abstract void 方法名();
    • B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
    • C:抽象类不能实例化
      • 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    • D:抽象类的子类
      • a:是一个抽象类。
      • b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。

09.07 抽象类的成员特点

    A:成员变量
        有变量,有常量
    B:构造方法
        有构造方法
    C:成员方法
        有抽象,有非抽象

09.08 抽象类的练习

  • A:猫狗案例练习

    /*
        猫狗案例
            具体事物:猫,狗
            共性:姓名,年龄,吃饭
    
        分析:从具体到抽象
            猫:
                成员变量:姓名,年龄
                构造方法:无参,带参
                成员方法:吃饭(猫吃鱼)
    
            狗:
                成员变量:姓名,年龄
                构造方法:无参,带参
                成员方法:吃饭(狗吃肉)
    
            因为有共性的内容,所以就提取了一个父类。动物。
            但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,
            而方法是抽象的类,类就必须定义为抽象类。
    
            抽象动物类:
                成员变量:姓名,年龄
                构造方法:无参,带参
                成员方法:吃饭();
    
        实现:从抽象到具体
            动物类:
                成员变量:姓名,年龄
                构造方法:无参,带参
                成员方法:吃饭();
    
            狗类:
                继承自动物类
                重写吃饭();
    
            猫类:
                继承自动物类
                重写吃饭();
    */
    //定义抽象的动物类
    abstract class Animal {
        //姓名
        private String name;
        //年龄
        private int age;
    
        public Animal() {}
    
        public Animal(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 eat();
    }
    
    //定义具体的狗类
    class Dog extends Animal {
        public Dog() {}
    
        public Dog(String name,int age) {
            super(name,age);
        }
    
        public void eat() {
            System.out.println("狗吃肉");
        }
    }
    
    //定义具体的猫类
    class Cat extends Animal {
        public Cat() {}
    
        public Cat(String name,int age) {
            super(name,age);
        }
    
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
    //测试类
    class AbstractTest {
        public static void main(String[] args) {
            //测试狗类
            //具体类用法
            //方式1:
            Dog d = new Dog();
            d.setName("旺财");
            d.setAge(3);
            System.out.println(d.getName()+"---"+d.getAge());
            d.eat();
            //方式2:
            Dog d2 = new Dog("旺财",3);
            System.out.println(d2.getName()+"---"+d2.getAge());
            d2.eat();
            System.out.println("---------------------------");
    
            Animal a = new Dog();
            a.setName("旺财");
            a.setAge(3);
            System.out.println(a.getName()+"---"+a.getAge());
            a.eat();
    
            Animal a2 = new Dog("旺财",3);
            System.out.println(a2.getName()+"---"+a2.getAge());
            a2.eat();
    
            //练习:测试猫类
        }
    }
    B:老师案例练习
    C:学生案例练习
    D:员工案例练习
    

09.09 抽象类的面试题(掌握)

    A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
        用于子类访问父类数据的初始化
    B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
        可以,为了不让创建对象,交给子类完成
    C:abstract不能和哪些关键字共存
        a:final 冲突  被final修饰的不让子类重写,所以重复
        b:private 冲突 private修饰的类是不让子类访问的
        c:static 无意义    被staic修饰的类可以通过类名调用,但是调用抽象方法是没有意义的

09.10 接口的概述及其特点

  • A: 接口概述
    • 从广义上讲对外提供规则的都是接口
    • 从狭义上讲指java中的interface
  • B: 接口的特点
    • a: 接口的关键字interface表示
      • interface 接口名{}
    • b: 接口的是先用implements 表示
      • class 类名 implements 接口名{}
    • c: 接口不能实例化
    • d:接口的实现类
      • a:是一个抽象类。意义不大
      • b:是一个具体类,这个类必须重写接口中的所有抽象方法。(推荐方案)

09.11 接口的成员特点

  • A: 接口的成员特点:
    • A:成员变量
      只能是常量
      默认修饰符:public static final
    • B:构造方法
      没有构造方法
    • C:成员方法
      只能是抽象的
      默认修饰符:public abstract

 09.12 类与类,类与接口,接口与接口

  • A:类与类 extends
    • 继承关系,只能单继承,可以多层继承
  • B:类与接口

    class 类名 implements A,B  
    
    • 实现关系,可以单实现,也可以多实现。
    • 还可以在继承一个类的同时,实现多个接口
  • C:接口与接口

    interface InterA extends InterB,InterC {…}

    • 继承关系,可以单继承,也可以多继承

09.13抽象类和接口的区别(必记)?

  • A: 成员区别  

    • 抽象类:
      • 成员变量:可以常量,可以变量
      • 成员方法:可以抽象,可以非抽象
      • 构造方法:有
    • 接口:
      • 成员变量:只能常量 public static final
      • 成员方法:只可以抽象
      • 构造方法:无
  • B: 关系区别:  

    • 类与类:
      • 继承,单继承
    • 类与接口:
      • 实现,单实现,多继承
    • 接口与接口:
      • 继承,单继承,多继承
  • C: 设计理念不同   
    • 抽象类:is a,抽象类中定义的是共性功能。
    • 接口:like a,接口中定义的是扩展功能。

 09.14 练习:

  • A:猫狗案例,加入跳高功能

    /*
    猫狗案例,加入跳高的额外功能
    
    分析:从具体到抽象
        猫:
            姓名,年龄
            吃饭,睡觉
        狗:
            姓名,年龄
            吃饭,睡觉
    
        由于有共性功能,所以,我们抽取出一个父类:
        动物:
            姓名,年龄
            吃饭();
            睡觉(){}
    
        猫:继承自动物
        狗:继承自动物
    
        跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口
        接口:
            跳高
    
        部分猫:实现跳高
        部分狗:实现跳高
    实现;
        从抽象到具体
    
    使用:
        使用具体类
    

    */
    //定义跳高接口
    interface Jumpping {
    //跳高功能
    public abstract void jump();
    }

    //定义抽象类
    abstract class Animal {
    //姓名
    private String name;
    //年龄
    private int age;

    public Animal() {}
    
    public Animal(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 eat();
    
    //睡觉(){}
    public void sleep() {
        System.out.println("睡觉觉了");
    }
    

    }

    //具体猫类
    class Cat extends Animal {
    public Cat(){}

    public Cat(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("猫吃鱼");
    }
    

    }

    //具体狗类
    class Dog extends Animal {
    public Dog(){}

    public Dog(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("狗吃肉");
    }
    

    }

    //有跳高功能的猫
    class JumpCat extends Cat implements Jumpping {
    public JumpCat() {}

    public JumpCat(String name,int age) {
        super(name,age);
    }
    
    public void jump() {
        System.out.println("跳高猫");
    }
    

    }

    //有跳高功能的狗
    class JumpDog extends Dog implements Jumpping {
    public JumpDog() {}

    public JumpDog(String name,int age) {
        super(name,age);
    }
    
    public void jump() {
        System.out.println("跳高狗");
    }
    

    }

    class InterfaceTest {
    public static void main(String[] args) {
    //定义跳高猫并测试
    JumpCat jc = new JumpCat();
    jc.setName(“哆啦A梦”);
    jc.setAge(3);
    System.out.println(jc.getName()+”—”+jc.getAge());
    jc.eat();
    jc.sleep();
    jc.jump();
    System.out.println(“—————–”);

        JumpCat jc2 = new JumpCat("加菲猫",2);
        System.out.println(jc2.getName()+"---"+jc2.getAge());
        jc2.eat();
        jc2.sleep();
        jc2.jump();
    
        //定义跳高狗并进行测试的事情自己完成。
    }
    

    }

  • B:老师和学生案例,加入抽烟功能0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值