继承
一个新类从已有的类那里获得其已有的属性和方法,这种现象叫类的继承
这个新定义的类称为子类或派生类,被继承的已经存在的类称为父类、超类或基类。
面向对象中的继承实际上就是从一般到特殊
下面举个例子
例1:
class Human {
String name = "张三";
int age = 20;
int high = 175;
int weight = 65;
}
class Student extends Human{
int num = 1201;
}
public class Test {
public static void main(String[] args) {
Student s = new Student();
System.out.printf("姓名:%s\n", s.name);
System.out.printf("年龄:%d\n", s.age);
System.out.printf("身高:%d\n", s.high);
System.out.printf("体重:%d\n", s.weight);
System.out.printf("学号:%d\n", s.num);
}
}
输出结果为:
姓名:张三
年龄:20
身高:175
体重:65
学号:1201
在上面的程序中,Human是基类,Student是子类,类的继承使用的关键字是extends,具体使用的情况见上面程序的第八行,由第15行到19行可知,Student类已经继承了Human类的属性
Human中拥有的属性Student中一定也有,如果没有继承,那那些属性又要从新在Student中定义,这导致代码的利用率不高,而且,通过继承,使得类的功能更加清晰,而且,利用继承可以较好的模拟出现实世界事物之间的联系
总之,继承的主要好处有:
代码的利用率得到极大的提高
形成一种类的体系结构
为多态创造了条件
另外,关于访问权限需要说明一下:
子类的所有方法(包括私有方法)都可以访问父类内部的所有非私有成员
通过子类对象名可以访问:
1、父类的所有非私有成员
2、子类的所有非私有成员
注:私有成员包括私有属性和私有方法
下面举个例子
例2:
class A {
private int s;
int m;
public int g;
protected int b;
private void fs() {
}
public void fg() {
}
void fm() {
}
protected void fb() {
}
}
class B extends A {
// 子类的所有方法内部都可以访问父类除私有成员以外的所有成员
private void g() {
m = g = 10;
fg();
fm();
fb();
// s = 10; //error
// fs(); //error
}
}
public class Test {
public static void main(String[] args) {
B bb = new B();
// 通过子类对象名可以访问父类除私有成员外的所有成员
bb.g = bb.b = bb.m = 22;
// bb.s = 11; //error
// bb.fs(); //error
bb.fg();
bb.fm();
bb.fb();
System.out.println("2014年6月30日08:41:46");
}
}
小结:
私有成员不能被继承
实际上,私有成员物理上已经被继承过来,只不过逻辑上程序员不能去访问它。因此,私有成员的继承必须慎重,否则会浪费内存
请看下图
√ 表示可以被继承和访问
还有,java只支持但继承,不允许多继承,所谓多继承就是一个子类只能有一个父类,当然,一个父类可以有多个子类
子类可以继承父类一般的所有成员变量和成员方法(尽管被继承的私有方法无法访问),但是子类永远无法继承父类的构造方法,当然,在子类的构造方法中可以使用语句super(参数列表)调用父类的构造方法
下面举个例子
例3:
class A {
public int i;
public int j;
public A() {
}
public A(int i, int j) {
this.i = i;
this.j = j;
}
}
class B extends A {
public int k;
public B() {
}
public B(int i, int j, int k) {
// A(i, j); //错误,不能直接调用父类的构造函数
super(i, j);// 这样可以调用父类的构造函数
this.k = k;
}
}
public class Test {
public static void main(String[] args) {
B bb = new B(1, 2, 3);
System.out.printf("i= %d j = %d\n", bb.i, bb.j);
System.out.printf("k = %d\n", bb.k);
}
}
输出结果为:
i= 1 j = 2
k = 3
需要注意的是:对super的调用必须在构造函数里边,且必须是构造函数的第一个语句;每个子类构造方法的第一条语句都隐含的调用了super()语句;如果将super()语句写出来,则必须保证父类中有无参数的构造函数,否则会出错;也可以这样写super(实参),当然,父类必须有带参数的构造函数;最后,一个子类的任何一个构造函数都只能出现一个super(参数列表)
【所有代码均在windows系统下eclipse环境JDK 1.7下运行通过】
(如有错误,敬请指正)