• 关于JAVA核心技术(卷一)读后的思考(继承中的类、子类和超类)


    前面说过类之间的关系有一种便是继承,其中“is-a”关系是继承的一个明显特征。举个例子有一个类是Employee,还有一个类是Manager类,Employee表示的是员工,而Manager表示的是老板,即管理层,而作为管理层也是员工,所以可以说这两者之间具有"is-a"这种关系。也就是说Manager是Employee的子类。

    定义子类:

    这里要用到一个关键字extends来表示继承。

    用上面的Employee例子就是:

    public class Manager extends Employee{

    ……

    }

    extends表明正在构造的新类派生于一个已存在的类。已存在的类成为超类;新类称为子类。

    在Manager类中有一个奖金信息的方法,具体为:

    public class Manager extends Employee {
        private double bonous;

    public void setBonous(double b) {
            bonous =b;
        }
        

    }
    即这个方法,在超类中并不存在,而在子类中存在,而在子类中并未显式地定义部分超类的方法,但仍然可以使用,因为Manager自动继承了超类Employee的方法。

    而对于构造函数有这样一个要求:

    当子类继承时,必须在自己的构造函数显式调用父类的构造函数,自己才能确保子类在初始化前父类会被实例化
    如果你父类中有无参的构造函数,子类就不会强制要求调用,即你写的那个就可以通过,
    编译器会默认帮你调用父类的构造函数。
    如果不按这个要求编译器会报错

     

    因为考虑到这些实例域都是private定义的,所以后面又把重新定义一边仍然报错,所以从侧面证明了这个原理

    方法覆盖

    超类的有些方法子类并不适用,所以这个时候就会进行提供一个新的方法来覆盖。

    子类的方法是不允许直接放为超类的私有域的,也就是说,尽管Manager对象都拥有一个名叫salary的域,但在Manager类的getSalary方法并不能直接访问salary域,必须调用超类中的公有的接口,才能使用通过。使用时,要加上super.getSalary,否则会无限调用自己,造成出错。

    子类可以增加域、增加方法或者覆盖超类的方法,却不能删除继承的任何域和方法

    子类构造器

    代码分析:

        public Manager(String name,double salary,int year,int month,int day) {
            super(name,salary,year,month,day);
              
            bonous=0;
            
        }

    其中的   super(name,salary,year,month,day);是调用超类的含对应参数的构造器。

    对该部分私有域进行初始化。我们用super实现对超类构造器的调用

    super调用构造器的语句必须是子类构造器的第一句

    如果子类的构造器没有显示地调用超类的构造器,则将自动地调用超类默认的构造器,若超类无无参数构造器,则会报错。

    package com.java.inheritance;

    public class ManagerTest {

        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Manager boss =new Manager("Carl Cracker",80000,1987,12,15);
            boss.setBonous(5000);
            Employee[] staff = new Employee[3];
            
            
            staff[0]=boss;
            staff[1]=new Employee("Harry Hacker",50000,1989,10,1);
            staff[2]=new Employee("Tommy Teter",40000,1990,3,15);
            
            for(Employee e:staff)
                System.out.println("name="+e.getName()+",salary="+e.getSalary());
            

        }

    }

    package com.java.inheritance;

    import java.time.*;

    public class Employee {
        private String name;
        private double salary;
        private LocalDate hireDay;
        
        public Employee(String name,double salary,int year,int month,int day)
        {
               this.name=name;
               this.salary=salary;
               hireDay=LocalDate.of(year, month, day);
               
        }
       /* public Employee() {
            
        }*/


        public String getName(){
            return name;
        }
        public double getSalary() {
            return salary;
            
        }
        public LocalDate getHireDay() {
            return hireDay;
        }
        public void raiseSalary(double byPercent) {
            double raise =salary*byPercent/100;
            salary+=raise;
        }

    }

    package com.java.inheritance;

    import java.time.LocalDate;

    public class Manager extends Employee {
        private double bonous;
        
        public Manager(String name,double salary,int year,int month,int day) {
        
            super(name,salary,year,month,day);
            bonous=0;
            
        }
        public  double getSalary() {
            double baseSalary=super.getSalary();
            return baseSalary+bonous;
            
        }
        public void setBonous(double b) {
            bonous =b;
        }
        

    }

    其中循环中有e.gatSalary()

    调用能够确定应该执行那个getSalary方法。尽管e声明为Employee类型,但实际是e技能引用Employee类型的对象,也可以引用Manager类型的对象。引用的是什么对象就是调用的是什么方法。

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

    继承层次

    继承并非限于一个层次。eg:Manager类派生Executive类。由一个公共超类派生出来的的所有类的集合称为继承层次,其中不管派生了几次都称为该类的继承层次

    在继承层次中,由某个特定的类到祖先的路径称为该类的继承链

    多态

    "is-a"规则是判定是否应该设计为继承关系的简单规则,即每个子类对象都是超类的对象。

    "is-a"规则是另一种表述法是置换法则,即两个对象进行置换观察是否任然满足条件。

    对象变量是多态的,一个Employee变量既可以引用Employee对象,也可以引用一个Employee的任何一个子类的对象。

    Employee[] staff = new Employee[3];
            
            
            staff[0]=boss;

    这是允许的,但编译器将staff[0]堪称Employee对象,

    意味着可以这样调用:

    boss.setBonous(5000);

    但不能

    staff[0].setBonus(5000);

    因为staff[0]声明类型是Employee,故不能调用子类方法。

    同时不允许将超类的引用赋值给子类变量。

    阻止继承:final类和方法

    不允许扩展的类称为final类。

    子类不允许覆盖的方法在前加final

    强制类型转换

    基本数据类型转换:

    低——>高:直接转换

    高——>低:强制类型转换

    方式:(类型名)变量名

    类:子类类型 变量名=(超类类型) 变量名

    超累类型 变量名=子类变量名       即:直接转换

    抽象类

    关键字:abstract

    即在超类中增加一个方法加上abstract,即可以不用实现这个方法

    而包含一个或多个抽象方法的类必须被声明为抽象的

    抽象方法充当着占位的角色,它的具体实现在子类中,扩展抽象类可以有两种选择,一种是在抽象类中定义部分抽象类方法或不定义抽象类方法,这样必须将子类也标记为抽象类。

    另一种是定义全部的抽象类方法

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

    抽象类不能实例化,即不能创建对象,但可以创建子类变量

    受保护访问

    关键字:protect

    使用这个关键字声明的实例域和方法,可以被该类的子类直接调用。

    不提倡使用

    访问修饰符总结总结

    (1)仅本类可以见——private

    (2)对所有类可见——public

    (3)对本包和所有子类可见——protect

    (4)对本包可见——默认(无修饰符)

    如果有写的不对的地方,欢迎指正,希望能够共同进步,谢谢!
  • 相关阅读:
    Mysql集群
    JAVA 经典算法 40 例
    公司面试问题总结
    面试题6
    面试题5
    Java自学-JDK环境变量配置
    mybatis中#{}和${}的区别
    JVM系列(四)— 原子性、可见性与有序性
    JVM系列(三)— Java内存模型
    Java基础拾遗(一) — 忽略的 Integer 类
  • 原文地址:https://www.cnblogs.com/zzuzhouxiang/p/10329775.html
Copyright © 2020-2023  润新知