一、继承的基础

在Java术语中,被继承的类叫超类(superclass)或者父类,继承超类的类叫子类(subclass).

举例说明:

 class Box
{
public double width;
public double height;
public double depth; //重载构造方法
public Box(Box ob)
{
width = ob.width;
height = ob.height;
depth = ob.depth;
} public Box(double w, double h, double d)
{
width = w;
height = h;
depth = d;
} public Box()
{
width = -1;
height = -1;
depth = -1;
} public Box(double len)
{
width = height = depth = len;
} //计算体积
public double volume()
{
return width * height * depth;
}
} //下面的类继承自类Box
class BoxWeight extends Box
{
double weight; //BoxWeight的构造方法
BoxWeight (double w, double h, double d, double m)
{
width = w;
height = h;
depth = d;
weight = m;
}
} public class DemoBoxWeight
{
public static void main(String args[])
{
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);
double vol; vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight);
System.out.println();
vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
}
}

如42行所示,声明一个继承超类的类,需要用到关键字extends,形式如下:

class subclass-name extends superclass-name {
// body of class
}

子类BoxWeight 包括超类Box所有成员,这就是为什么在49-51行中子类可以直接给超类的成员赋值,并且子类对象mybox1可以调用超类方法volume()的原因。而且一个子类可以是另一个类的超类。

但是一个子类只允许有一个超类(这与C++不同,C++中派生类可以继承多个基础类),任何类不能成为自己的超类。

运行结果:

继承的一个主要优势在于一旦你已经创建了一个超类,而该超类定义了适用于一组对象的属性,它可用来创建任何数量的说明更多细节的子类。每一个子类能够正好制作它自己的分类。上面的BoxWeight类继承了Box并增加了一个重量属性。 每一个子类只增添它自己独特的属性。

二、成员的访问权限和继承

尽管子类包括超类的所有成员,但是它不能访问超类中被声明成private的成员,一个被类定义成private的类成员为此类私有,它不能被该类外的所有代码访问。

类成员的访问控制通常有四种public,protected,default,private,下图对各种控制模式的允许访问范围作一个总结:

三、超类变量可以引用子类对象

 class Box
{
public double width;
public double height;
public double depth; //重载构造方法
public Box(Box ob)
{
width = ob.width;
height = ob.height;
depth = ob.depth;
} public Box(double w, double h, double d)
{
width = w;
height = h;
depth = d;
} public Box()
{
width = -1;
height = -1;
depth = -1;
} public Box(double len)
{
width = height = depth = len;
} //计算体积
public double volume()
{
return width * height * depth;
}
} //下面的类继承自类Box
class BoxWeight extends Box
{
double weight; //BoxWeight的构造方法
BoxWeight (double w, double h, double d, double m)
{
width = w;
height = h;
depth = d;
weight = m;
}
}
class RefDemo
{
public static void main(String args[])
{
BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37);
Box plainbox = new Box();
double vol; vol = weightbox.volume();
System.out.println("Volume of weightbox is " + vol);
System.out.println("Weight of weightbox is " +
weightbox.weight);
System.out.println();
// assign BoxWeight reference to Box reference
plainbox = weightbox; vol = plainbox.volume(); // OK, volume() defined in Box
System.out.println("Volume of plainbox is " + vol); /* The following statement is invalid because plainbox
does not define a weight member. */
// System.out.println("Weight of plainbox is " + plainbox.weight);
}
}

weightbox是BoxWeight对象的一个引用,plainbox是Box对象的一个引用(关于JAVA中引用的概念和C++有些不同,可以参考http://blog.sina.com.cn/s/blog_7fb1495b01012sfn.html,写的很详细)。既然 BoxWeight是Box的一个子类,允许用一个weightbox对象的引用给plainbox赋值,但是plainbox是不可以访问weight的,因为超类不知道子类增加的属性weight,所以最后一行被注释掉,Box的引用访问weight域是不可能的,因为它没有定义这个域。

四、关于super

super有两种通用形式。第一种调用超类的构造方法。第二种用来访问被子类的成员隐藏的超类成员。

  • 使用super调用超类构造函数

考虑下面BoxWeight()的改进版本:

class BoxWeight extends Box
{
double weight; //BoxWeight的构造方法
BoxWeight (double w, double h, double d, double m)
{
super(w, h, d);// 调用超类构造方法
weight = m;
}
}

这样Box完全可以把成员width,height,depth声明为private,子类在初始化这些成员时并没有自己动手,而是调用超类的构造方法去初始化这些值(超类自己的构造方法显然可以访问自己private成员),这样有利于超类的封装。而且超类将根据super里面参数的形式决定调用哪一个构造方法,看下面程序:

 class Box
{
//成员全部“私有化”
private double width;
private double height;
private double depth; //重载构造方法
public Box(Box ob)
{
width = ob.width;
height = ob.height;
depth = ob.depth;
} public Box(double w, double h, double d)
{
width = w;
height = h;
depth = d;
} public Box()
{
width = -1;
height = -1;
depth = -1;
} public Box(double len)
{
width = height = depth = len;
} //计算体积
public double volume()
{
return width * height * depth;
}
} //下面的类继承自类Box
class BoxWeight extends Box
{
double weight; //用super调用BoxWeight的构造方法
BoxWeight(BoxWeight ob)
{
super(ob);
weight = ob.weight;
} BoxWeight (double w, double h, double d, double m)
{
super(w, h, d);
weight = m;
}
// default constructor
BoxWeight() {
super();
weight = -1;
} BoxWeight(double len, double m) {
super(len);
weight = m;
}
}
public class myJavaTest
{
public static void main(String args[]) {
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);
BoxWeight mybox3 = new BoxWeight(); // default
BoxWeight mycube = new BoxWeight(3, 2);
BoxWeight myclone = new BoxWeight(mybox1);
double vol; vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight);
System.out.println(); vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
System.out.println(); vol = mybox3.volume();
System.out.println("Volume of mybox3 is " + vol);
System.out.println("Weight of mybox3 is " + mybox3.weight);
System.out.println(); vol = myclone.volume();
System.out.println("Volume of myclone is " + vol);
System.out.println("Weight of myclone is " + myclone.weight);
System.out.println();
vol = mycube.volume();
System.out.println("Volume of mycube is " + vol);
System.out.println("Weight of mycube is " + mycube.weight);
System.out.println();
}
}

运行结果:

这里特别注意这个构造方法:

    BoxWeight(BoxWeight ob)
{
super(ob); //子类对象赋给超类对象
weight = ob.weight;
}

可以看出一个超类引用了子类对象,但是超类只知道它自己的成员,而weight它是不知道的,需要单独初始化。

特别记住,super()必须是子类构造方法中第一个执行的语句。

  • super的第二种用法

通用形式:super.超类的成员域, 其中“超类的成员域”可以是成员变量和成员方法。多数是用于超类成员名被子类中同样的成员名隐藏的情况,看一个简单的例子:

1 class A
2 {
3 int xiaoming;
4 }
5
6 class B extends A {
7 int xiaoming; // 这子类中的同名变量xiaoming会隐藏超类中的xiaoming
8
9 B(int a, int b) {
10 super.xiaoming = a; // xiaoming in A
11 xiaoming = b; // xiaoming in B
12 }
13
14 void show()
15 {
16 System.out.println("xiaomingin superclass: " + super.xiaoming);
17 System.out.println("xiaoming in subclass: " + xiaoming);
18 }
19 }
20
21 class UseSuper
22 {
23 public static void main(String args[])
24 {
25 B subOb = new B(1, 2);
26
27 subOb.show();
28 }
29 }

输出如下:

xiaoming in superclass: 1

xiaoming in subclass: 2

这个例子只是展示了super可以访问被子类隐藏的超类的成员变量,但是不要忘记,super同样可以访问被子类隐藏的超类的成员方法。

Java学习笔记之继承的更多相关文章

  1. 1.8(java学习笔记)继承与方法的重写

    继承 在java中可以通过继承提高代码的复用率. 例如A继承了B,就可以是 例如,首先有一个类似Person,这个类中有有一些属性和方法,我们再新建一个Student类,其中有一部分属性和方法与Per ...

  2. Java 学习笔记(6)——继承

    之前说过了Java中面向对象的第一个特征--封装,这篇来讲它的第二个特征--继承.一般在程序设计中,继承是为了减少重复代码. 继承的基本介绍 public class Child extends Pa ...

  3. Java学习笔记之——继承

    父类(基类):动物 子类:猫.狗.狼.老虎 如果子类继承于父类,则会自动拥有父类的所有非私有属性和方法,不会继承构造方法 父类和子类要满足一种关系:子类是父类的一种 Java中只支持单继承:一个子类只 ...

  4. java学习笔记1——继承

    通过在类的声明中加入extends子句创建一个子类并继承父类的成员变量和方法.如: class SubClass extends SuperClass{ ... } 若SuperClass是另一个类的 ...

  5. 0022 Java学习笔记-面向对象-继承、多态、组合

    继承的特点 单继承:每个子类最多只有一个直接父类,注意是直接父类,间接父类个数不限 注意父类的概念:A-->B-->C-->D,在这里,ABC都是D的父类,C是D的直接父类,AB是D ...

  6. java学习笔记之基础篇

    java选择语句之switch   //switch可以用于等值判断 switch (e) //int ,或则可以自动转化成int 的类型,(byte char short)枚举jdk 7中可以防止字 ...

  7. java学习笔记6--类的继承、Object类

    接着前面的学习: java学习笔记5--类的方法 java学习笔记4--类与对象的基本概念(2) java学习笔记3--类与对象的基本概念(1) java学习笔记2--数据类型.数组 java学习笔记 ...

  8. 0035 Java学习笔记-注解

    什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...

  9. 0032 Java学习笔记-类加载机制-初步

    JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...

随机推荐

  1. A woman without arms

    任吉美出生在中国烟台海阳一个极为普通的渔民家里.她先天残疾,没有胳膊和手. 小吉美注定要比别人生活得更艰难.她不能自己穿衣,不能自己端碗吃饭,也不能像兄弟姐妹们一样帮助妈妈干家务活,她觉得自己成了家里 ...

  2. android 状态栏、标题栏、屏幕高度

    1.获取状态栏高度: decorView是window中的最顶层view,可以从window中获取到decorView,然后decorView有个getWindowVisibleDisplayFram ...

  3. python+selenium环境搭建

    这里主要基于windows平台. 下载python.http://python.org/getit/ 下载setuptools [python的基础包工具].http://pypi.python.or ...

  4. PHP.ini 配置文件解析

    [PHP] ;;;;;;;;;;;;;;;;;;;; About php.ini   ;;;;;;;;;;;;;;;;;;;;; PHP's initialization file, generall ...

  5. unity3d Human skin real time rendering 真实模拟人皮实时渲染(转)

    先放出结果图片...由于网上下的模型是拼的,所以眼皮,脸颊,嘴唇看起来像 存在裂痕,解决方式是加入曲面细分和置换贴图 进行一定隆起,但是博主试了一下fragment shader的曲面细分,虽然细分成 ...

  6. STL六大组件之——适配器代表大会

    适配器也是一种常用的设计模式: 将一个类的接口转换为另一个类的接口,使得原本因接口不兼容而不能合作的两个类可以一起运作.STL提供三种适配器:改变容器接口的容器适配器.改变迭代器接口的迭代器适配器以及 ...

  7. python的元组和列表使用之一

    Python的列表和元组 1.       概述 列表是用方括号[]包围的数据集合,不同的成员之间用逗号进行分隔,列表可以通过序号来进行访问其中的成员,可以对列表进行排序.添加.删除操作,改变列表中某 ...

  8. 大数据时代的数据存储,非关系型数据库MongoDB

    在过去的很长一段时间中,关系型数据库(Relational Database Management System)一直是最主流的数据库解决方案,他运用真实世界中事物与关系来解释数据库中抽象的数据架构. ...

  9. C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期

    全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...

  10. HDU ACM 1051/ POJ 1065 Wooden Sticks

    Wooden Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...