【JAVA基础】08 面向对象3

1. 多态

  • 多态polymorhic概述

    • 事物存在的多种形态。
  • 多态前提
    • 要有继承关系
    • 要有方法重写
    • 要有父类引用指向子类对象
  • 案例演示
    • 代码体现多态
    • class  Demo1_Polymorphic{
          public static void main(String[] args) {
              Cat c = new Cat();
              c.eat();
      
              Animal a = new Cat(); // 父类引用指向子类对象
              a.eat();  // 输出“猫吃鱼”
          }
      }
      
      
      class Animal {
          public void eat() {
              System.out.println("动物吃饭");
          }
      }
      
      class Cat extends Animal {
          public void eat() {
              System.out.println("猫吃鱼");
          }
      }
  • 多态中的成员访问特点
    • 成员变量
      • 编译看左边(父类),运行看左边(父类)
      • Father f = new Son();
      • class Demo2_Polymorphic {
            public static void main(String[] args) {
                Father f = new Son();
                System.out.println(f.num); //输出10
            }
        }
        
        class Father {
            int num = 10;
        
        }
        
        class Son extends Father {
            int num = 20;
        }

         【JAVA基础】08 面向对象3

         如果再上面例子的基础上,再生成一个Son类对象,则

      • class Demo2_Polymorphic {
            public static void main(String[] args) {
                Father f = new Son();
                System.out.println(f.num); //输出10
        
                Son s = new Son();
                System.out.println(s.num);   //输出20
            }
        }
        
        class Father {
            int num = 10;
        
        }
        
        class Son extends Father {
            int num = 20;
        }

         【JAVA基础】08 面向对象3

    • 成员方法
      • 编译看左边(父类),运行看右边(子类)——又称“动态绑定”
      • Father f = new Son();
      • 编译时,看父类中有没有该成员方法,有则编译成功;运行则动态绑定到子类的成员方法上,运行子类的成员方法。
      • class Demo3_Polymorphic {
            public static void main(String[] args) {
                Father f = new Son();
                f.print();// 输出son
            }
        }
        
        class Father {
            int num = 10;
        
            public void print() {
                System.out.println("father");
            }
        
        }
        
        class Son extends Father {
            int num = 20;
        
            public void print() {
                System.out.println("son");
            }
        }

         【JAVA基础】08 面向对象3

    • 静态方法
      • 编译看左边(父类),运行看左边(父类)
      • 静态和类相关,算不上重写,所以,访问还是左边的
      • class Demo4_Polymorphic {
            public static void main(String[] args) {
                Father f = new Son();
                f.method();  //输出"father static method";
                // 相当于是Father.method(); 调用父类的方法
            }
        }
        
        class Father {
            int num = 10;
        
            public void print() {
                System.out.println("father");
            }
        
            public static void method(){
                System.out.println("father static method");
            }
        
        }
        
        class Son extends Father {
            int num = 20;
        
            public void print() {
                System.out.println("son");
            }
        
            public static void method(){
                System.out.println("son static method");
            }
        }
    • 总结:
      • 只有非静态的成员方法,编译看左边(父类),运行看右边(子类)
      • 其他都是编译看左边(父类),运行看左边(父类)
  • 案例:超人的故事
    • 通过该案例帮助理解多态的现象。
    • class Demo5_Polymorphic {
          public static void main(String[] args) {
              Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人
      
              System.out.println(p.name);// 输出“John”
              p.谈生意();  // 输出"谈几个亿的大单子"
              
              
              //p.fly();  //编译出错
              
          }
      }
      
      class Person {
          String name = "John";
      
          public void 谈生意() {
              System.out.println("谈生意");
          }
      }
      
      class SuperMan extends Person {
          String name = "Super man";
      
          public void 谈生意() {
              System.out.println("谈几个亿的大单子");
          }
      
          public void fly() {
              System.out.println("飞出去救人");
          }
      }
      View Code

超人作为人类身份的属性信息对外展示,Person类和SuperMan类中重写的方法,实际执行的是超人身份的方法;

在这个例子中,父类中没有fly方法,故编译失败,也无法执行。针对这个,要考虑下面的 向上转型和向下转型 的问题。
  • 多态中 向上转型和向下转型
    • 向上转型
      • Person p = new SuperMan();
      • 父类引用指向子类对象,就是向上转型
    • 向下转型
      • SuperMan sm = (SuperMan)p;
      • class Demo5_Polymorphic {
            public static void main(String[] args) {
                Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人
        
                System.out.println(p.name);// 输出“John”
                p.谈生意();  // 输出"谈几个亿的大单子"
                
                
                //p.fly();  //编译出错
        
                SuperMan sm = (SuperMan)p; // 向下转型
                sm.fly();
                
            }
        }
        
        class Person {
            String name = "John";
        
            public void 谈生意() {
                System.out.println("谈生意");
            }
        }
        
        class SuperMan extends Person {
            String name = "Super man";
        
            public void 谈生意() {
                System.out.println("谈几个亿的大单子");
            }
        
            public void fly() {
                System.out.println("飞出去救人");
            }
        }

【JAVA基础】08 面向对象3

  • 补充参考:基本数据类型:
    • 自动类型提升
    • 强制类型转换
    • class  Demo1_Polymorphic{
          public static void main(String[] args) {
              int i = 10;
              byte b = 20;
              i = b;  // 自动类型转换
              b = (byte)i;  // 强制类型转换
              
          }
      }
  • 多态的好处和弊端
    • 多态的好处
      • 提高了代码的维护性(继承保证)
      • 提高了代码的扩展性(由多态保证)
        • 可以当做形式参数
        • 可以接收任意子类对象
    • 多态的弊端
      • 不能使用子类的特有属性和行为
    • 案例演示
      • method(Animal a)  方便Animal的所有子类的 重写的方法调用
      • method(Cat c)  这种直接调用子类,出现并行子类,调用父类方法,需要些新的method方法,传入不同的类作为实参。
      • class Demo6_Polymorphic {
            public static void main(String[] args) {
                
                method(new Cat());
                method(new Dog());  
                /* 
                Animal a = new Cat();
                Animal a = new Dog();
                
                开发的时候很少在创建对象的时候用父类引用指向子类对象,
                直接创建子类对象更方便,可以使用子类中的特有属性和方法
                
                */
        
            }
        
            /*
            public static void method(Cat c) {
                c.eat();
            }
        
            public static void method(Dog d) {
                d.eat();
            }*/
        
            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();
                }
        
                
                /*
                // 如果把Dog强转成Cat,就会出现类型转换异常,ClassCastException
                Cat c = (Cat)a;
                c.eat();
                c.catchMouse();*/
            }
        }
        
        class Animal {
            public void eat() {
                System.out.println("动物吃饭");
                }
        }
        
        class Cat extends Animal {
            public void eat() {
                System.out.println("猫吃鱼");
            }
        
            public void catchMouse() {
                System.out.println("抓老鼠");
            }
        }
        
        class Dog extends Animal {
            public void eat() {
                System.out.println("狗吃肉");    
            }
        
            public void lookHome() {
                System.out.println("看家");
            }
        }
        View Code 

2. 抽象类

  • 抽象类概述
    • 抽象就是看不懂的
  • 抽象类的特点
    • 抽象类和抽象方法必须用abstract关键字修饰
      • abstract class 类名 ()
      • public abstract void eat();
    • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者接口
    • 抽象类不能实例化,那么,抽象类如何实例化呢?
      • 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    • 抽象类的子类
      • 要么是抽象类
      • 要么重写抽象类中的所有抽象方法
    • 案例演示
      • class Demo1_Abstract {
            public static void main(String[] args) {
        
                Animal a = new Cat();
                a.eat();
                print(a);
            }
        
            public static void print(Animal a) {
                a.eat();
            }
        }
        
        
        abstract class Animal { // 抽象类
             public abstract void eat();  // 抽象方法
        }
        
        
        class Cat extends Animal {
        
            public void eat() {
                System.out.println("猫吃鱼");
            }
        
        }
        View Code
  • class Demo1_Abstract {
        public static void main(String[] args) {
    
            
        }
    
        public static void print(Animal a) {
            a.eat();
        }
    }
    
    
    abstract class Animal { // 抽象类
         public abstract void eat();  // 抽象方法
    }
    
    class Cat extends Animal {
    
        //错误: Cat不是抽象的, 并且未覆盖Animal中的抽象方法eat()
    
    }
    View Code
  • 抽象类联系(猫狗,抽象类为动物)
  • class Test2_Teacher {
        public static void main(String[] args) {
            Teacher t = new BaseTeacher();
            print(t);
    
            print(new EmpTeacher());
            
        }
        
        public static void print(Teacher t) {
            t.teach();
        }
    }
    
    /*
    具体事物:基础班老师,就业班老师
    共性:姓名、年龄、讲课
    */
    
    abstract class Teacher {
        private String name;
        private int age;
        
        public abstract void teach();
    
    
        public Teacher() {}
    
        public Teacher(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int getAge() {
            return age;
        }
    
    }
    
    class BaseTeacher extends Teacher {
        public BaseTeacher() {}
    
        public BaseTeacher(String name, int age) {
            super(name, age);
        }
    
    
        public void teach() {
            System.out.println("基础班老师 讲课");
        }
    
    }
    
    
    class EmpTeacher extends Teacher {
        public EmpTeacher() {}
    
        public EmpTeacher(String name, int age) {
            super(name, age);
        }
    
    
        public void teach() {
            System.out.println("就业班老师 讲课");
        }
    
    }
    老师抽象类
  • class Test3_Student {
        public static void main(String[] args) {
            state(new BaseStudent());
            state(new EmpStudent());
        }
    
        public static void state(Student s) {
            s.study();
        }
    }
    
    
    /*
    具体事物:基础班学生,就业班学生
    共性:姓名,年龄,学习
    */
    
    abstract class Student {
        private String name;
        private int age;
        
        public abstract void study();
    
        public Student() {}
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getNamge() {
            return name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int getAge() {
            return age;
        }
    
    }
    
    class BaseStudent extends Student {
        public BaseStudent() {}
    
        public BaseStudent(String name, int age) {
            super(name,age);
        }
    
        public void study() {
            System.out.println("基础班学生在学习");
        }
    }
    
    class EmpStudent extends Student {
        public EmpStudent() {}
    
        public EmpStudent(String name, int age) {
            super(name,age);
        }
    
        public void study() {
            System.out.println("就业班学生在学习");
        }
    }
    学生抽象类
  • class Test4_Employee {
        public static void main(String[] args) {
            Coder c = new Coder("John", "001", 10000.00);
            c.work();
    
            Manager m = new Manager("Ann", "033", 40000.00, 10000);
            m.work();
            
        }
    }
    
    /*
    假如我们在开发一个系统时,需要对程序员类进行设计。
    程序员包含3个属性:
        姓名
        工号
        工资
    
    经理:出了含有程序员的属性外,还有一个奖金属性
    
    用继承的思想设计出程序员类和经理类。
    要求类中提供必要的方法进行属性访问。
    
    */
    
    abstract class Employee {
        private String name;
        private String code;
        private double salary;
    
        public Employee() {}
    
        public Employee(String name, String code, double salary) {
            this.name = name;
            this.code = code;
            this.salary = salary;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName(){
            return name;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getCode(){
            return code;
        }
    
        public void setSalary(double salary) {
            this.salary = salary;
        }
    
        public double getSalary(){
            return salary;
        }
    
        public abstract void work();
    
        
    }
    
    
    class Manager extends Employee {
        private int bonus;
    
        public Manager() {}
    
        public Manager(String name, String code, double salary, int bonus) {
            super(name,code,salary);
            this.bonus = bonus;
        }
    
        public void setBonus(int bonus) {
            this.bonus = bonus;
        }
    
        public int getBonus(){
            return bonus;
        }
        
        
        public void work() {
            System.out.println("项目经理" + this.getName() + "在工作");
            System.out.println("奖金是" + this.getBonus());
        }
    
    }
    
    
    class Coder extends Employee {
        public Coder() {}
    
        public Coder(String name, String code, double salary) {
            super(name,code,salary);
        }
        
        public void work() {
            System.out.println("程序员" + this.getName() + "在工作");
        }
    
    }
    雇员:程序员,项目经理
  • 抽象类的注意问题
  • 3. 接口

    3. 各种类,接口之间的关系

    3.1 类与类,类与接口,接口与接口的关系

     3.2 抽象类和接口的区别

    4. 包package

    5. 修饰符

    6. 内部类

    相关推荐