绑定: 将方法的调用与方法本身相联系叫“绑定”
绑定分为前绑定与后绑定。前绑定是指绑定发生在程序运行之前。后绑定是指绑定发生在程序运行的时候,根据对象的类型来决定具体应该绑定哪个方法。后绑定也被称为“动态绑定”或者“运行时绑定”。除了 static和 final方法,java的所有方法都是后绑定。也就是说所有的 static,final,private的方法都不能被覆写。
这样做的好处是,实现多态的方法调用,我们就可以只关心同基类相关的部分。
例如
class
Shape
{
void draw();
void erase();
}

class
Circle
extends
Shape
{
void draw(){
System.out.println("Circle.draw()");
}
void erase(){
System.out.println("Circle..erase()");
}
}

class
Square
extends
Shape
{
void draw(){
System.out.println("Square.draw()");
}
void erase(){
System.out.println("Square..erase()");
}
}

class
Triangle
extends
Shape
{
void draw(){
System.out.println("Triangle.draw()");
}
void erase(){
System.out.println("Triangle..erase()");
}
}
基类Shape为继承类定义了共用的接口(方法),派生类再覆写这些方法,提供自己特有的方法。
当
Shape s
=
new
Circle();
程序运行时自己知道应该调用 Circle的方法。
然而这样做的话,又会带来一些问题。因为基类Shape只是做了定义,却没有真正的去实现。所以当调用基类的方法时,就会报错。解决的办法就是使用抽象类和抽象方法来阻止对基类方法的调用。如果继承了抽象类,并且打算创建一个新类的对象,那么就必须实现抽象类(基类)的全部抽象方法。上面的例子可以变为:
abstract
class
Sharp
{
public abstract void draw();
public abstract void erase();
}

class
Circle
extends
Shape
{
void draw(){
System.out.println("Circle.draw()");
}
void erase(){
System.out.println("Circle..erase()");
}
}

class
Square
extends
Shape
{
void draw(){
System.out.println("Square.draw()");
}
void erase(){
System.out.println("Square..erase()");
}
}

class
Triangle
extends
Shape
{
void draw(){
System.out.println("Triangle.draw()");
}
void erase(){
System.out.println("Triangle..erase()");
}
}
构造函数的调用顺序
1,调用基类的构造函数,这是一个递归,也就是由最原始的父类开始调用
2,成员对象按照声明的顺序进行初始化
3,执行继承类自身的构造函数
其中有一个问题:如果构造函数调用了一个动态绑定的方法,而且这个方法属于那个正在创建的对象,那么构造函数应该怎么做?
abstract
class
Shape
{
abstract void draw();

Shape(){
System.out.println("Shape() before draw()");
draw();
System.out.println("Sharp() after draw()");
}
}

class
Circle
extends
Shape
{
private int radius = 1;
Circle(int r){
radius = r;
System.out.println("Circle.Circle(), radius = "+ radius);
}
void draw(){
System.out.println("Circle.draw(), radius = " + radius);
}

}

public
class
Sharp
{
public static void main(String[] args){
new Circle(5);
}
}
得到的结果为:
Shape() before draw()
Circle.draw(), radius = 0
Sharp() after draw()
Circle.Circle(), radius = 5
所以开始说的调用顺序应当改为:
1,对象初始化为0
2,调用基类的构造函数,这是一个递归,也就是由最原始的父类开始调用。调用的同时会调用被覆写的方法。
3,成员对象按照声明的顺序进行初始化
4,执行继承类自身的构造函数
但是这样会带来许多意想不到的bug。所以一个好的构造函数应当是它只能调用final的方法,因为final的方法不能覆写。
绑定分为前绑定与后绑定。前绑定是指绑定发生在程序运行之前。后绑定是指绑定发生在程序运行的时候,根据对象的类型来决定具体应该绑定哪个方法。后绑定也被称为“动态绑定”或者“运行时绑定”。除了 static和 final方法,java的所有方法都是后绑定。也就是说所有的 static,final,private的方法都不能被覆写。
这样做的好处是,实现多态的方法调用,我们就可以只关心同基类相关的部分。
例如































基类Shape为继承类定义了共用的接口(方法),派生类再覆写这些方法,提供自己特有的方法。
当

程序运行时自己知道应该调用 Circle的方法。
然而这样做的话,又会带来一些问题。因为基类Shape只是做了定义,却没有真正的去实现。所以当调用基类的方法时,就会报错。解决的办法就是使用抽象类和抽象方法来阻止对基类方法的调用。如果继承了抽象类,并且打算创建一个新类的对象,那么就必须实现抽象类(基类)的全部抽象方法。上面的例子可以变为:































构造函数的调用顺序
1,调用基类的构造函数,这是一个递归,也就是由最原始的父类开始调用
2,成员对象按照声明的顺序进行初始化
3,执行继承类自身的构造函数
其中有一个问题:如果构造函数调用了一个动态绑定的方法,而且这个方法属于那个正在创建的对象,那么构造函数应该怎么做?




























得到的结果为:
Shape() before draw()
Circle.draw(), radius = 0
Sharp() after draw()
Circle.Circle(), radius = 5
所以开始说的调用顺序应当改为:
1,对象初始化为0
2,调用基类的构造函数,这是一个递归,也就是由最原始的父类开始调用。调用的同时会调用被覆写的方法。
3,成员对象按照声明的顺序进行初始化
4,执行继承类自身的构造函数
但是这样会带来许多意想不到的bug。所以一个好的构造函数应当是它只能调用final的方法,因为final的方法不能覆写。