JAVA学习脚印5: 继承特性及特殊类

来源:互联网 发布:java编写中文软件 编辑:程序博客网 时间:2024/04/29 08:52

JAVA学习脚印5: 继承特性及特殊类

本节将学习类的继承特性及一些特殊类,本节所述实例中的类设计参考自《java核心技术》。


1.java继承特点

 

· java中使用关键字extends表示继承,所有的继承都是公有public继承(区别于c++中的三种继承方式即public、protected、private)。

· 子类中可以增加域、增加方法或者覆盖超类的方法,但是绝对不能删除继承的任何域和方法。因此在设计类的时候应该将通用的方法放在超类中,而将具有特殊用途的方法放在子类中。

· 子类可以通过super关键字类调用超类的方法或者超类的构造器,可以使用this关键字类引用隐式参数或者调用本类的其他构造器。注意super关键字不是一个对象的引用,不能将其赋给另一个对象变量,它只是一个编译器调用超类方法的特有关键字。

经理与雇员类的设计如图1所示:


图1 职员与经理类的继承关系图


测试代码如例5-1:

5-1 ManagerTest.java

package com.learningjava;import java.util.Date;import java.util.GregorianCalendar;/** * this program demonstrate inheritance * from the book 《Core Java,Volume I:Fundamentals》 */public class ManagerTest {public static void main(String[] args) {Employee[] staffs = new Employee[3];staffs[0] = new Employee("Steve",5000,1985,9,4);staffs[1] = new Employee("Jason",6000,1983,8,12);Manager mgr = new Manager("Jery",8000,1980,11,7);mgr.setBonus(5000);staffs[2] = mgr;for(Employee item : staffs)System.out.println("name= "+item.getName()+",salary= "+item.getSalary());}}/** * a class to descript employee * from the book 《Core Java,Volume I:Fundamentals》 */class Employee {/** * @param name name to set * @param salary salary to set * @param hireday hireday to set */public Employee(String name, double salary, Date hireday) {this.name = name;this.salary = salary;this.hireday = hireday;setId();}/** *  * @param name name to set * @param salary salary to set * @param year month day  to create a GregorianCalendar */public Employee(String name, double salary, int year,int month,int day) {this.name = name;this.salary = salary;GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);this.hireday = calendar.getTime();setId();}public void raiseSalary(double percent) {double raise = salary*percent/100;salary += raise;}public String getName() {return name;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Date getHireday() {return hireday;}public void setHireday(Date hireday) {this.hireday = hireday;}public int getId() {return id;}private void setId() {this.id = nextId;nextId++;}private String name; private double salary;private Date hireday;private int id;private static int nextId = 1;}/** *  a class to descript manager * */class Manager extends Employee {public void setBonus(double b) {bonus = b;}public Manager(String name, double salary, int year,int month,int day) {super(name, salary,year,month,day);bonus = 0;}public Manager(String name, double salary, Date hireday) {super(name, salary, hireday);bonus = 0;}@Overridepublic double getSalary() {double baseSalary = super.getSalary();return baseSalary+bonus;}private double bonus;}

· 检验是否应该使用继承的规则

类之间最常见的有三种关系即,依赖(use-a)、聚合(has-a)、继承(is-a)关系。

is-a表明子类的每个对象也是超类的对象。例如每个经理都是雇员,因此可以将Manager类设计成为Employee类的子类,反之每个雇员却并不都是经理。

2.java中的特殊类

1) final类——阻止继承

如果希望阻止人们继承某个类,可以使用final关键字将该类定义为final类,String类就是一个final类,声明为public final class String。final关键字作用于类的域时称为final域,表明该域在构造对象以后就不能修改其值了;final作用于方法时称为final方法,表明该方法不能被子类覆盖。注意,final类的方法自动地成为final方法,而域不自动为final域。

阻止继承主要是为了确保它们不会在子类中改变语义。

 

2) abstract类——高层次抽象

抽象类是对类进行高度抽象后形成的类,它比一般类更加通用。

规定,包含一个或多个抽象方法的类本身必须声明为抽象类。

抽象方法起着占位的作用,它的具体实现在它的具体实现子类中。注意,拓展抽象类有两种选择。一种是在子类中定义全部的抽象的方法,这样一来,子类不再抽象;还有一种是子类中定义部分抽象方法或抽象方法也不定义,这样子类也成为抽象类。

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

  注意,抽象类不能创建出实例,而只作为派生其他类的基类。但是可以定义一个抽象类的  对象引用变量,用于引用非抽象子类的对象。

例如设计一个抽象类层次如下图2所示:



抽象继承关系

具体可参考例5-2:

5-2  PersonTest.java

package com.learingjava;import java.util.Date;import java.util.GregorianCalendar;/** * this program demonstrates abstract classes * from the book 《Core Java,Volume I:Fundamentals》 */public class PersonTest {public static void main(String[] args) {Person[] people = new Person[2];//fill arraypeople[0] = new Employee("Steven",5000,1985,9,4);people[1] = new Student("Jobs","computer science");//print infofor(Person item : people)System.out.println(item.getName()+","+item.getDescription());}}/** * an abstract class  * with abstract method getDescription() */abstract class Person {public Person(String name) {super();this.name = name;}    public String getName() {    return name;    }    //abstract method    public abstract String getDescription();private String name;}/** * a class to descript employee * from the book 《Core Java,Volume I:Fundamentals》 */class Employee extends Person{/** * @param name name to set * @param salary salary to set * @param hireday hireday to set */public Employee(String name, double salary, Date hireday) {super(name);this.salary = salary;this.hireday = hireday;setId();}/** *  * @param name name to set * @param salary salary to set * @param year month day  to create a GregorianCalendar */public Employee(String name, double salary, int year,int month,int day) {super(name);this.salary = salary;GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);this.hireday = calendar.getTime();setId();}public void raiseSalary(double percent) {double raise = salary*percent/100;salary += raise;}@Overridepublic String getDescription() {return String.format("an employee with a salary of ¥%.2f", salary);}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Date getHireday() {return hireday;}public void setHireday(Date hireday) {this.hireday = hireday;}public int getId() {return id;}private void setId() {this.id = nextId;nextId++;}private double salary;private Date hireday;private int id;private static int nextId = 1;}/** * a class to descript student * */class Student extends Person {/** *  * @param name the student's name * @param major the student's major */public Student(String name,String major) {super(name);//pass the name to the superclass constructorthis.major = major;}@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn "a student majoring in "+major;}private String major;}

3) Object类——所有类的超类


java中每个类都是由Object类派生而来的,如果没有明确指出某个类的超类,则该类的超类就是Object。

注意,Object类作为所有类的超类,这种类型的引用变量可以引用任何类型的对象。

但是要想对其引用的对象进行具体的操作,还需要清楚该对象该的原始类型,并进行相应的类型转换。如:

Object obj = new Student("Jobs","computer science");

Student stu = (Student) obj;//change to the origin type

还要注意,所有的数组类型,不管是对象数组还是基本数据类型的数组都拓展于Object类。

Student[] students = new Student[10];

Object obj =  students;//ok

Object类有四个关键方法,需要我们注意,参见《JAVA学习脚印7:  Object类的四个关键方法》


4)enum枚举类

java中所有的枚举类型都是Enum类的子类,定义简单的枚举类如下:

public enum Size {SMALL,MEDIUM,LARGE,EXTRAL_LARGE};可以给枚举类增加构造函数、方法和域。

获取枚举常量时使用Enum类的静态方法valueOf,其原型为:

public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name)

例如: Size size = Enum.valueOf(Size.class, "SMALL");构造了枚举变量

注意,在比较两个枚举类型的值时,不要使用equals,而是直接使用"=="就可以了。


5)Class类

java运行时系统始终为所有的对象维护一个被称为运行时的类型标识,这个信息保存着每个对象所属的类足迹,保存着些信息的类被称为Class类。例如如下代码:

Manager mgr = new Manager("Jery",8000,1980,11,7);Class<? extends Manager> cl = mgr.getClass();System.out.println(cl.getName());System.out.println(cl.getClass().getName());

输出:com.learningjava.Manager

       java.lang.Class

Class对象表示一个特定类的属性,例如这里的cl表示com.learningjava.Manager类的属性。

Class类是java语言提供的反射库中的一个类,能够分析类能力的程序被称为反射(reflective)。反射机制主要应用在工具构造上,反射机制可参考:《java学习脚印:Class类与反射机制》。



0 0
原创粉丝点击