继承
- 为了继承,一般的规则是把所有的数据成员都指定为private,将所有的方法都指定为public。
- Java的super关键字表示超类,当前类就是从超类继承而来的。为此,表达式super.scrup()将调用基类版本的scrub()方法。
- 子类重写父类的方法的访问修饰符,权限不可以降低。
初始化基类
基类构造器总是会被调用,并且是在导出类构造器之前被调用
package com.chao.chapterSeven;
class Base1{
public Base1() {
System.out.println("Base1");
}
}
class Derived1 extends Base1{
public Derived1() {
System.out.println("Derived1");
}
}
class Derived2 extends Derived1{
public Derived2() {
System.out.println("Derived2");
}
}
public class E04_ConstructorOrder {
public static void main(String[] args) {
new Derived2();
}
}
带参数的构造器
super
之前各类中均含有默认构造器,即这些构造器都不带参数。编译器可以轻松地调用它们是因为不必考虑传递什么样的参数的问题。
但是,如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显示地编写调用基类构造器的语句,并且配以适当的参数列表。
/**
*
* */
package com.chao.chapterSeven;
class Game{
//有参数的基类构造器
public Game(int i) {
System.out.println("Game constructor");
}
}
class BoardGame extends Game {
public BoardGame(int i) {
//调用基类构造器必须是你在导出类构造器中要做的第一件事
//如果注释掉super(i),编译器将会抱怨无法找到符合Game()形式的构造器
//super(i)在这里的作用就是帮助BoardGame找到基类的构造器Game(i)
super(i);
System.out.println("BoardGame constructor");
}
}
public class Chess extends BoardGame{
public Chess() {
super(11);
System.out.println("Chess constructor");
}
public static void main(String[] args) {
Chess chess = new Chess();
}
}
代理(是做什么用的?)
确保正确的清理
package com.chao.chapterSeven;
class Shape{
public Shape(int i) {
System.out.println("Shape constructor");
}
void dispose(){
System.out.println("Shape dispose");
}
}
class Circle extends Shape{
public Circle(int i) {
super(i);
System.out.println("Drawing circle");
}
void dispose(){
System.out.println("Erasing circle");
super.dispose();
}
}
class Triangle extends Shape{
public Triangle(int i) {
super(i);
System.out.println("Drawing triangel");
}
void dispose(){
System.out.println("Earsing triangle");
super.dispose();
}
}
class Line extends Shape{
private int start, end;
public Line(int start, int end) {
super(start);
this.start = start;
this.end = end;
System.out.println("Drawing line:" + start + "," + end);
}
void dispose(){
System.out.println("Earsing line: " + start + "," + end);
super.dispose();
}
}
public class CADSystem extends Shape{
private Circle c;
private Triangle t;
private Line[] lines = new Line[3];
public CADSystem(int i) {
super(i);
for (int j = 0; j < lines.length; j++)
lines[j] = new Line(j, j*j);
c = new Circle(1);
t = new Triangle(1);
System.out.println("Combined constructor");
}
public void dispose(){
System.out.println("CADSystem.dispose()");
t.dispose();
c.dispose();
for(int i = lines.length-1; i >= 0; i--){
lines[i].dispose();
}
super.dispose();
}
public static void main(String[] args) {
CADSystem x = new CADSystem(47);
try{
}finally{
x.dispose();
}
}
}
看一下执行的结构
Shape constructor
Shape constructor
Drawing line:0,0
Shape constructor
Drawing line:1,1
Shape constructor
Drawing line:2,4
Shape constructor
Drawing circle
Shape constructor
Drawing triangel
Combined constructor
CADSystem.dispose()
Earsing triangle
Shape dispose
Erasing circle
Shape dispose
Earsing line: 2,4
Shape dispose
Earsing line: 1,1
Shape dispose
Earsing line: 0,0
Shape dispose
Shape dispose
执行类的所有的特定的清理动作,其顺序同生成顺序相反,上例子可知。
protected关键字
前面介绍完了继承,关键字***protected***最终具有了意义。在实际项目中,经常会想要将某些事物隐藏起来,但任允许导出类的成员访问它们。
它指明“就用类用户而言,这是private的,但对于任何继承于此类的导出类或其他任何一个位于这个包内的类而言,他却是可以访问的。”
###向上转型
假如有一个称为Instrument的代表乐器的基类和一个称为Wind的导出类。由于继承可以确保基类中所有的方法在导出类中也同样有效,所以能够向基类发送的所有信息同样也可以向导出类发送。这意味着我们可以准确地说Wind对象也是一种类型的Instrument。
再谈向上转型
向上转型对象不是父类创建的对象,而是子类对象的“简化版”。它不关心子类新增的功能,只关心子类继承和重写的功能。当一个类有很多个子类时,并且这些子类都重写了父类中的某个方法,也就是说,不同向上转型的对象调用同一方法可能可能产生不同的行为。
再再谈向上转型
List list = new ArrayList();
当list使用的方法,如果List和ArrayList都有时,用的是ArrayList的方法,如果ArrayList有而List没有就报错,呵呵多态啊,如果要想用ArrayList中的所有的方法就ArrayList arrayList = (ArrayList)list强转,父类类型的变量始终能够引用子类对象,这是多态啊
向上转型的好处
toString()方法
Object类具有一个toString()方法,你创建的每个类都会继承该方法。它返回对象的一个String表示。对于默认的toString()往往不能满足需求,需要覆盖这个方法。
例如,如果打印一个对象,打印出的就是toString()方法返回的内容