继承

作者: 须臾之北 | 来源:发表于2018-07-18 22:39 被阅读0次

    继承

    1. super关键字的学习

    • 逻辑关系:

      • Manager继承Employee成为Employee的一个子类
      • Manager的实例域增加了bonus属性
      • Manager类中相应增加了setBonus()方法
    • super关键字

      • 在计算Manager的salary时,我们需要家和奖金bonus,而父类的实例域均为private,由于,Manager类的构造器不可以访问Empoloyee类的私有域,所以,我们用super来实现子类对父类中构造器和方法的使用
    • Employee类

        import java.time.LocalDate;
            
        class Employee{
            
            //data field
            private String name;
            private double salary;
            private LocalDate hireDay;
            
            //constructor
            public Employee(String name,double salary,int year,int month,int day){
                this.name = name;
                this.salary = salary;
                this.hireDay = LocalDate.of(year,month,day);
            }
            
            //method
            public String getName(){
                return name;    
            }
            
            public double getSalary(){
                return salary;  
            }
            
            public LocalDate gethireDay(){
                return hireDay;
            }
            
            public void raiseSalary(double byPercent){
                salary += salary * byPercent/100;
            }
        }
      
    • Manager类

        class Manager extends Employee{
            private double bonus;
            
            public void setBonus(double bonus){
                this.bonus = bonus;
            }
            
            public Manager(String name,double salary,int year,int month,int day){
                super(name,salary,year,month,day);
                bonus = 0;  
            }
            
            public double getSalary(){
                return bonus + super.getSalary();
            }
        }
      
    • super.getSalary();

      • 调用父类的getSalary()方法
    • super(name,salary,year,month,day);

      • 调用父类的Employee(String name,double salary,int year,int month,int day)构造器
    • ManagerTest类

        public class Test{
            public static void main(String[] args){
                Manager boss = new Manager("hahaha",200,2018,7,16);
                boss.setBonus(50);
                
                Employee[] staff = new Employee[3];
                staff[0] = boss;
                staff[1] = new Employee("xixixi",100,2018,7,16);
                staff[2] = new Employee("xixixi",100,2018,7,16);
                
                //输出所有的Employee信息
                for(Employee e : staff){
                    System.out.println("name : " + e.getName() + ",salary : " + e.getSalary()); 
                }
            }   
        }
        /*
            在JDK1.8中输出结果为:
            ------------------------------
            name : hahaha,salary : 250.0
            name : xixixi,salary : 100.0
            name : xixixi,salary : 100.0
            ------------------------------
        */
      
    • super与this的区别

      • this的两个用途

        • 一是引用隐士参数
          • this.name = name;
        • 二是调用该类其他的构造器
          • this(name,salary)
      • super的两个用途

        • 一是调用超类的方法
          • super.getSalary()
        • 二是调用超类的构造器
          • super(name,salary,year,month,day);

    2. 多态与动态绑定

    • 输出所有的Employee信息

        for(Employee e : staff){
            System.out.println("name : " + e.getName() + ",salary : " + e.getSalary()); 
        }
      
    • 当e引用Employee对象时,e.getSalary()调用的是Employee类中的getSalary()方法,当e引用Manager对象时,e.getSalary()调用的是Manager类中的getSalary()方法。

    • 一个对象变量可以指示多种实际类型的现象被称为多态,在运行时能够自动地选择调用哪个方法的现象称为动态绑定。

      • 可理解为:多态就是父类的引用指向子类对象。此时,对象变量是多态的。
    • 多态类型

      • 方法的多态
        • 方法的重载:
          • 方法名称相同,参数类型和个数不同,与返回值无关
        • 方法的重写(继承中使用)
          • 方法名称、参数类型、返回值与父类一致
      • 对象的多态
        • 父类的引用指向子类对象

    3. 阻止继承:final类和方法

    • 回顾:

      • 实例域声明为final时,构造对象之后就不允许改变他们的值
    • 当类声明为final时,则不允许继承扩展

      • final类中的所有方法自动成为final方法
    • 当方法声明为final时,子类将不能覆盖这个方法。

    • 强制类型转换

      • Manager为Employee一个子类,此时:
        • Employee boss = new Manager();

        • 若要调用Manager类中特定方法setBonus(),则需要强制类型转换

            if(boss instanceof Manager){
                Manager bos = (Manager)boss;
                bos.setBouns(500);       
            }
          
        • 向下转型的强制类型转换不太常见。

    4. 访问控制符号

    • private
      • 仅对本类可见
    • protected
      • 对本包和所有子类可见
    • public
      • 对所有类可见

    抽象类

    1. 抽象类相关概念

    • 包含一个或者多个抽象方法的类本身被声明为抽象的

    • 除抽象方法外,抽象类还可以包含具体的数据和具体方法

    • 类即使不含有抽象方法,也可以将类声明为抽象类

    • 抽象类不能被实例化

    • 可以定义一个抽象类的对象引用,指向引用一个非抽象子类的实例化对象

        Person p = new Student(); 
      

    2. 抽象类的使用举例

    • 定义抽象类Person
      • 抽象方法getDescription();
      • 具体方法:getName();
            public abstract class Person{
                private String name;
                public abstract String getDescription();
                
                public Person(String name){
                    this.name = name;
                }
                
                public String getName(){
                    return name;
                }
            }
    
    • 定义抽象类子类Employee类

        import java.time.LocalDate;
      
        class Employee extends Person{
            private double salary;
            private LocalDate hireDay;
            
            public Employee(String name,double salary,int year,int month,int day){
                    super(name);
                    this.salary = salary;
                    hireDay = LocalDate.of(year,month,day);
            }
            
            public String getDescription(){
                return String.format("an employee with a salary of $.2f",salary);   
            } 
            
            public double getSalary(){
                return salary;
            }
            
            public LocalDate gethireDay(){
                return hireDay; 
            }
            
            public void raiseSalary(double byPercent){
                salary += salary * byPercent/100;
            }
        }
      
    • 定义抽象类的子类Student类

        class Student extends Person{
            private String major;
            
            public Student(String name,String major){
                super(name);
                this.major = major;
            }
            
            public String getDescription(){
                return "a student majoring in" + major;
            }
        }
      
    • Person类测试

        public class PersonTest{
            public static void main(String[] args){
                Person[] people = new Person[2];    
                
                people[0] = new Employee("hahaha",200,2018,7,17);
                people[1] = new Student("xixixi","CS");
                
                for(Person p : people){
                    System.out.println(p.getName() + " , " + p.getDescription());
                }       
            }   
        }
      
        /*
            1. 此时涉及到对象的多态:父类的引用指向子类对象
            2. 父类类型数组中存放着子类的实例化对象
            3. 虽然Person为抽象类,但是
                Persoon[] people = new Person[3];仍然正确
        */
      

    Object类

    • 所有类的超类
      • equals()方法

        • Object中的equals用于检测一个对象是否等于另外一个对象。
        • Object中是判断两个对象是否为同一引用
        • 我们需要重写equals()方法
      • Employee中重写equals方法

          public class Employee{
              ......
                  
              public boolean equals(Object otherObject){
                  //判断使用为同一引用
                  if(otherObject == this)
                      return true;
                  
                  //判断otherObject是否为空
                  if(otherObject == null)
                      return false;
                  
                  //判断是否属于同一类
                  if(getClass() != otherObject.getClass())
                      return false;
                  
                  //现在可知Employee为otherObject的一个实例化对象
                  Employee other = Employee(otherObject);
              
                  //判断是否相等
                  return this.name == other.name && this.salary = other.salary && this.hireDay == other.hireDay;
              }
        
          }
        

    泛型数组列表

    优点

    • 动态的更改数组的大小
    • 可存放任意类型的数组

    例子

    • 声明和构造一个保存Employee对象的数组列表

      ArrayList<Employee> staff = new ArrayList<>();
      <>中为Employee

    • 为数组列表中添加Employee对象

      staff.add(new Employee("hahah",200,2018,7,16));

    • 返回当前数组中的元素个数

      staff.size();

    缺点

    • 不太方便获取数组列表中的元素
    • 因此在遍历数组列表时,可以将数组列表转换为数组
      • 扩展数组,并添加所有元素

        ArrayList <X> list = new ArrayList<>();
        while(....){
        x = ....;
        list.add(x);
        }

        X[] a = new X[list.size()];
        list.toArray(a);

    相关文章

      网友评论

          本文标题:继承

          本文链接:https://www.haomeiwen.com/subject/nsaapftx.html