zoukankan      html  css  js  c++  java
  • Java继承

    超类与子类

    1.概念

    Java用关键字extends表明正在构造的新类派生于一个已经存在的类。已存在的类称为超类(superclass),基类(base class)或父类(parent class);新类称为子类(subclass),派生类(derived)或孩子类(child class)。Java程序员一般使用术语超类和子类。

    超类相比于子类并没有优于子类或拥有比子类更多的功能。相反,子类可能封装了更多的数据或功能。

    一个例子:

    class Employee {
        private int id;
        private String name;
        private double salary;
        public Employee(String name,double salary){
           ...
        }
        public String getName() 
        public double getSalary() {
            return salary;
        }
        public int getId() 

    这样一个公司员工的类。属性有id,名字,薪水。

    公司有经理,经理的待遇与普通员工有一些差异,不过差异不大。比如,经理在干完活后可以领取奖金,普通员工只能领取薪水,其他都一样。此时,面对这样一点小小的差异,我不愿意从头到尾编写一个新的类,那么就要用到继承。

    为经理定义一个新类Manager,增加一点新功能,然后重用Emploee的部分代码即可,将其所有域保留下来。两者之间存在一种明显的关系,is-a关系。即每名经理也是一个员工。

    每个子类也是一个超类。is-a关系是继承的一个明显特征。

    增加奖金域:

    public class Manager extends Emploee{
        private double bonus;
        ....
        public double setBonus(double bonus){
            this.bonus = bonus;
        }
        ....
    }

    这样,子类就可以使用超类一些方法,因为Manager类自动继承了Emploee中的这些方法。但Emploee却不能使用setBonus()方法。

    2.覆盖方法

    事实上,子类继承自父类的方法,有些不太适用于子类,例如,父类的getSalary()方法,返回薪水。经理的薪水是怎样的呢?显然,是原来的薪水加奖金。

    使用下面的方法来覆盖父类的getSalary()方法:

    public double getsalary(){
        double baseSalary = super.getSalary();
        return baseSalary + bonus;
    }

    这里用到了super关键字。直接return salary+bonus;这样的语句是不行的。

    原因:Manager的getSalary()方法不能直接访问超类的私有域。只有Emploee类的方法才能访问。

    因此,借助super调用超类的方法,可帮助我们访问超类中的域。

    3.子类构造器

    同样需要借助super构造器。因为需要访问超类私有域。

    public Manager(String name,double salary,int id){
        super(name,salary,id);
        bonus = 0;    
    }

    这样简写,当超类构造器有对应的参数的构造方法时,即会调用那个构造函数。若无,会产生错误。

    如果子类没有显示的使用super调用超类的构造器,则自动调用超类的默认(无参数)构造器。

    4.多态

    现有一经理,两员工,输出薪水。

    Employee[] staff = new Employee[3];
    Manage boss = new Manager(); 
    staff[0] = boss;
    staff[1] = new Employee();
    staff[2] = new Employee();
    for (Employee e:staff){
      system.out.println(e.getSalary());
    }

    这段代码能够正确的输出薪水。jvm在运行时能够自动的选择调用正确的方法,引用超类时调用超类方法,引用子类时调用子类方法。虚拟机知道e实际引用的对象类型,正确调用方法。

    一个对象变量能够指示不同多种实际类型的现象称为多态。

    在运行时能够自动选择调用哪个方法的现象称为动态绑定。

    如上例子,staff[0]赋值给e,即将一个子类的对象赋值给超类,e即引用了两种实际类型。这里,编译器将staff[0]看做Emploee对象,因而不能这样调用:staff[0].setBonus(5000);可以这样调用:boss.setBonus(5000);

    不能将超类的引用赋值给子类变量,原因是显而易见的,相反的is-a关系。

    5.阻止继承

    有时候,希望阻止某个类定义子类。不允许拓展的类称为final类。如果在定义类时使用了而final修饰符,就表明这个这个类是final类。

    public final class Executive extends Manager{
    ...
    }

    类中的方法也可以定义为final方法,这样做子类就不能覆盖该方法。

    public final String getName()

    6.抽象类和抽象方法

    有时候,希望父类更加通用,派生出多种多样的子类,并且只将父类作为派生其他类的基类,而不作为想使用的特定的实例类。

    这时,即可使用抽象类。

    抽象类中可以有抽象方法,抽象方法只有声明而没有实现。如:

    public abstract class Person{
        ...
        public abstract String getDescription();
    }

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

    抽象类的实现在子类中,有以下两种方式:

    1)在抽象类中定义部分抽象方法或不定义抽象方法,那么就必须将子类声明为抽象类。

    2)在抽象类中定义全部抽象方法,子类就不是抽象的了

    抽象类不能被实例化

    可以定义一个抽象类的对象,但它只能引用非抽象类子类的对象。

    Person p = new Student();

    p引用的是子类Student的对象。

    7.可见性控制

    1)仅对本类可见---private

    2)对所有类可见---public

    3)对本包和所有子类可见---protected

    4)对本包可见---默认

    Object:所有类的超类

    Object类是java中所有对象的超类,每个类都继承自Object。

    以下是Object类的一些方法

    1.equals方法

    作用:检测一个对象是否等于另一个对象。实际上是判断两个对象是否具有相同的引用。

    有些情况下,需要重写该方法,即有时检测而两个对象状态的相等性而不是引用。

    覆盖equal方法的一种实现

    1)显示参数命名为otherObject

    2)检测this是否与otherObject引用同一对象,是返回true,否继续

    if(this==otherObject) return true;

    3)检测otherObject是否为null,是返回false,否继续

    if(otherObject==null) return false;

    4)比较this与otherObject是否为同一个类,(如果equals语义在每个子类中有所改变,使用getClass()方法;一致则使用instanceof),不是返回false,是继续

    if(getClass()!=otherObject.getClass()) return false;

    if(!(otherObject instance ClassName)) return false;

    这里是考虑由超类决定相等概念还是由子类决定相等概念。

    5)将otherObject转换成相应的类类型变量,比较所有域。

    ClassName other = (ClassName) otherObject

    .....

    2.hashcode方法

    hashcode是由对象导出的一个整形值。散列码是没有规律的。如果x和y是两个不同的对象,那么它们的散列值基本不会相同。

    相同的字符串拥有相同的散列码。例如:String s ="OK",String t =new String("OK"), s.hashcode()和t.hashcode()返回结果都是2524。这是因为字符串散列码由内容导出。

    如果重写quals方法,那么就需要重写hashcode方法,以便将对象插入到散列表中。

    3.toString方法

    作用:返回表示对象值的字符串

    一般用于获取对象状态

  • 相关阅读:
    out/host/linuxx86/obj/EXECUTABLES/aapt_intermediates/aapt 64 32 操作系统
    linux 查看路由器 电脑主机 端口号 占用
    linux proc进程 pid stat statm status id 目录 解析 内存使用
    linux vim 设置大全详解
    ubuntu subclipse svn no libsvnjavahl1 in java.library.path no svnjavahl1 in java.library.path no s
    win7 安装 ubuntu 双系统 详解 easybcd 工具 不能进入 ubuntu 界面
    Atitit.json xml 序列化循环引用解决方案json
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    Atitit.跨语言  文件夹与文件的io操作集合  草案
    Atitit.atijson 类库的新特性设计与实现 v3 q31
  • 原文地址:https://www.cnblogs.com/lht-record/p/8361430.html
Copyright © 2011-2022 走看看