`

008 面向对象之继承

 
阅读更多

1、继承(Inheritence):Java是单继承的,意味着一个类只能从另一个类继承(被继承的类叫做父类【基类,baseclass】, 继承的类叫做子类),Java中的继承使用extends关键字。

2、当生成子类对象时,Java默认首先调用父类的不带参数的构造方法,然后执行该构造方法,生成父类的对象。接下来,再去调用子类的构造方法,生成子类的对象。【要想生成子类的对象,首先需要生成父类的对象,没有父类对象就没有子类对象。比如说:没有父亲,就没有孩子】。

3、super关键字:super表示对父类对象的引用。 如果子类使用super()显式调用父类的某个构造方法,那么在执行的时候就会寻找与super()所对应的构造方法而

不会再去寻找父类的不带参数的构造方法。与this一样,super也必须要作为构造方法的第一条执行语句,前面不能有其他可执行语句。

4、对于有继承关系的两个类,执行继承类时会生成两个对象,先生成父类对象,且两个类在内存中的存放是挨着的,这样子类才可能知道父类的地址,对其继承。

11. 关于继承的3点:

a) 父类有的,子类也有

b) 父类没有的,子类可以增加

c) 父类有的,子类可以改变

12. 关于继承的注意事项

a) 构造方法不能被继承

b) 方法和属性可以被继承

c) 子类的构造方法隐式地调用父类的不带参数的构造方法

eg: classFahter{

public father()

{

}

}

      class Child extends Father{

public Child()

{

super();  /*此语句一般省略,即隐式调用*/

}

}

d) 当父类没有不带参数的构造方法时,子类需要使用super来显

式地调用父类的构造方法,super指的是对父类的引用

e) super关键字必须是构造方法中的第一行语句。

 

16. 在定义一个类的时候,如果没有显式指定该类的父类,那么该类就会继承于java.lang.Object类(JDK提供的一个类,Object类是Java中所有类的直接或间接父类)。

 

抽象类的继承 在子类继承父类(父类是个抽象类)的情况下,那么该子类必须要实现父类中所定义的所有抽象方法;否则,该子类需要声明成一个abstract class。

 

再谈类的继承

 

 

在一开始就提到了面向对象编程语言的三大特性:封装、继承和多态。

 

现在来说说继承。这个特性是基于重用的需求产生的。

 

面向对象程序设计的一个重要的特点就是类的重用。

 

这可以通过两种方法来实现:一种是将一个类的实例当作另一个类的属性。也可以使用类的继承来实现,通过关键字extends,可以使一个类继承另一个类,使这个类也具有被继承类的特点。

 

实现继承的类称为子类,而被继承的类称为父类,也称为超类。

 

类的继承是面向对象程序设计的一个重要特点。

 

另一种就是组合。实际上在软件设计开发应用中,组合的使用较之于继承更频繁,但是不专属于面向对象的特性罢了。

 

我们来看一个例子,假设现在要开发一个用于学校的管理系统,这个系统中有教师和学生,我们可以给教师定义一个类,就像下面一样:
public class Teacher{
 String name;//姓名
 int age;//年龄
 String sex;//性别
 String department;//属于哪个教研室
 public void setName(String theName){… …}
 public String getName(){… …}
 … …
}


而相对于一个学生,也可以定义一个类,如下:
public class Student{
 String name;//姓名
 int age;//年龄
 String sex;//性别
 String grade;//年级
 public void setName(String theName){… …}
 public String getName(){… …}
 … …
}

仔细分析这两个类,可以发现这两个类结构上非常类似,比如:姓名、年龄、性别,唯一的区别就在于“老师”类有一个属性“department”,用于说明老师是属于哪个教研室;而“学生”类有一个属性“grade”,表示这个学生是在几年级就读。

 

倘若现在需要在这两个类上新增一个属性:生日,那么,必须在这两个类上都作修改。

 

其实,在面向对象的编程方法中,完全可以将这两个类的一些共性抽象出来,当作这两个类的“父类”。例如,这两个类中的姓名、年龄、性别都是作为一个“人”所共有的特性,因此,可以将这些特性抽取出来,作为一个新的类:Person,如下:
public class Person{
 String name;
 int age;
 String sex;
 public void setName(String theName){… …}
 public String getName(){… …}
 … …
}

然后,根据需要,使学生和老师这两个类都继承这个“Person”类,再在这个基础上添加上自己特有的一些特性,例如“学生”类如下:
public class Student extends Person{
 //不再需要定义姓名、年龄、性别这些属性了,
//它们从父类“Person”中获得
 String grade;//年级
 public void setGrade(String theGrade){… …}
 public String getGrade(){… …}
 … …
}


而“教师”类可以如下定义:
public class Teacher extends Person{
 //同样不需要定义姓名、年龄、性别这些属性,
//而从父类“Person”中获得
 String department;//部门
 public void setDepartment(String theDept){… …}
 public String getDepartment(){… …}
 … …
}


通过这种方式,就可以共用父类“Person”的特性,这时,如果需要给“学生”和“老师”都加上“生日”这个属性,只需要在它们共同的父类“Person”上加上这个属性就可以了。如下:
public class Person{
 String name;
 int age;
 String sex;
 java.util.Date birthday;//新增生日属性,类型为一个Date引用类型
 //加上对这个属性进行操作的方法
 public void setBirthday(java.util.Date theDate){… …}
 public java.util.Date getBirthday(){… …}
 … …
}


如果这时候,需要在这个管理系统中新增一个对学校职工的管理功能,需要新增一个“职工”类,它也可以使用“Person”类中定义的属性,然后再加上自己特有的属性,代码如下:
public class Employee extends Person{
 //在此加上“职工”特有的属性
}

 

在这个例子中,“Person”类称为“Student”、”Teacher”、”Employee”这三个类的“父类”或“超类”(SuperClass),而“Student”、”Teacher”、”Employee”称为“Person”类的“子类”(SubClass)。

从上面的例子中,可以看到,如果一个子类要继承父类,只要使用关键字“extends”即可。

 

在Java中,类继承的基本语法如下:
<modifier>  class  <name>  [extends <superclass> ]{
 <declaration> *
}


其中,用关键字“extends”来进行类的继承,后面紧跟的是父类的类名。


在Java中,一个类只能从一个父类继承,而不能从多个类中继承。这种继承方式称为“单继承”。这点和C++等其他面向对象语言程序的开发是不同的。


在java.lang包中有一个Object类,这个类是所有类的顶级父类。所有的Java类,包括标准库中的类和自己定义的类,都直接或间接的继承了这个类。这个类没有任何的属性,只是定义了一些方法。

 

因此,只要你定义了一个Java类,就有一些默认的方法供你调用。


在Java中,如果你定义了一个类,这个类没有继承任何的父类,那么,系统会自动将这个类的父类设置为java.lang.Object,例如上面定义的Person这个类:
public class Person{ … …}
它实际上等价于:
public class Person extends java.lang.Object{ … …}


实际上,你在定义一个类的时候也确实可以这样来写,只是,这个工作完全可以由系统来代劳。


在Java中,虽然一个子类只能继承一个父类,但是,一个父类却可以“派生”出任意多个的子类。这种状况有点类似于生活中的“父子关系”:一个父亲可以生几个孩子,而一个孩子却只能有一个生父(养父、继父以及“认贼作父”等等情况不算)。

 

所谓“派生”,只是从父类的角度来看类的继承。也就是说,“继承”是从子类的角度来看父类和子类的关系的,而“派生”却是从父类的角度来看父类和子类的关系的。

我们用另一个例子来说明类的继承。

首先我们定义一个类“Animal”,用来表示“动物”这个物种。
源文件:Animal.java
public class Animal {
 private int weight;

 public int getWeight() {
  return weight;
 }

 public void setWeight(int w) {
  weight = w;
 }
}


它有一个构造器,用动物的体重来作为参数。有一个表示体重的属性weight,以及用于存取这个属性的两个方法:getWeight()和setWeight()。


然后我们定义一个子类Dog,这个子类继承自Animal,因此,此时这个类也拥有了父类Animal的属性和相应的方法。在此基础上,又在子类上新增了一个用于描述狗叫的方法:Bark。


public class Dog extends Animal {
 // 子类新增方法
 public void Bark() {
  System.out.println("Wang~~Wang~~~");
 }
}


最后我们来看如何实例化这个Dog类,以及如何在Dog中体现它和父类Animal的关系。

public class MyDog {
 private static Dog myDog;

 public static void main(String args[]) {
  myDog = new Dog();
  myDog.setWeight(50);
  System.out.println("My Dog's Weight is" + myDog.getWeight());
  myDog.Bark();
 }
}


在这个MyDog类中,首先调用Dog的构造器来实例化了一个Dog类,此时得到一个myDog对象,然后,调用Dog从父类继承的setWeight()方法来设置它的属性weight,以及调用从父类继承的getWeight()方法来获取属性weight的值。最后,调用Dog类自身定义的方法Bark()。

运行这个程序,将在控制台上打印出如下信息:
My Dog’s Weight is 50
Wang~~Wang~~~

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics