Think In Java笔记(五)

Polymorphism And Interface

1.方法绑定。程序运行前,使用绑定,我们称之为预先绑定。还有动态绑定,java即采用动态绑定,在程序运行时才作用。Java里的所有方法都是动态绑定,除了static和final还有private方法。如果父类有方法a,子类没有覆盖a,那么通过upcast,call a(),将会调用父类的方法,如果覆盖了,则调用子类的a方法。

Exercise 2

package polymorphism;

public class Circle extends Shape{
    public void draw() {System.out.println("Circle.draw()");}
    public void erase() {System.out.println("Circle.erase()");}
    public void print() {System.out.println("this is circle print");
    }
}
/*output:Triagnle.draw()
this is print
Triagnle.draw()
this is print
Square.draw()
this is print
Triagnle.draw()
this is print
Square.draw()
this is print
Triagnle.draw()
this is print
Square.draw()
this is print
Triagnle.draw()
this is print
Circle.draw()
this is circle print
 */

 Exercise10

package polymorphism;

public class Exercise10 {
    public static void main(String[] args) {
        One t = new Two();
        t.a(); //output:this is two b 
    }
}

class One{
    void a(){
        b();
    }
    void b() {
        System.out.println("this is a");
    }
}

class Two extends One{
    void b() {
        System.out.println("this is two b");
    }
}

2.当子类upcast为父类的引用,所有数据域都不会遵循多态的规则,调用父类的引用将会直接调用父类的数据域,而非子类。所以注意,最好不要将子类和父类的数据域变量名设置一样,或者设置为private,以便父类的数据域隐藏起来。

3.实际的构造器call顺序,在父类构造器call之后,所有被overriden的方法也会被call。接下来才是其他的初始化。

Interface

1.抽象方法(abstract method),一旦一个类拥有抽象方法,那么这个类必须声明为抽象类,抽象类不可实例化,因为抽象类本身就是未完成的类。如果要从一个抽象类继承,那么必须实现所有的抽象方法。注意,就算你的类里没有抽象方法,也是可以被声明为抽象(abstract)的(即此类不可被实例化)。由练习03可以看出,当调用一个抽象父类的构造器时,如果这个构造器调用了父类的抽象方法,那么会自动调用子类的完整方法(如果该方法在子类被正确override)。

Exercise02

package interfaces;

public class Exercise02 { // won't work
    public static void main(String[] args) {
        A a = new A();//cannot initialize abstract class of A
    }
}

abstract class A{
    void b(){
        System.out.println("this is A");
    }
}

Exercise03

package interfaces;

public class Exericse03 extends X{
    private int t = 1;
    void print(int x){
        t = x;
        System.out.println(t);
    }
    public static void main(String[] args) {
        new Exericse03().print(3);; //output:2,3
    }
}

abstract class X{
    X(){
        print(2);
    }
    abstract void print(int i);
}

 4.接口可以包含数据域,但是必须为static,final。可以继承任意数量的接口,implements后面用逗号连接,注意,如果时非接口的继承,只能继承一个。如果需要同时继承自一个实体类(非接口)和接口类,那么实体类需要写在前面。

实际应用中选择接口类还是抽象类?如果你希望创建一个没有任何定义的方法或者成员变量的基类,那么用接口类。

另外,由于java不支持多继承,所以不存在菱形继承问题,虽然接口可以多继承,但是,注意一点,接口是没有成员变量的,而且所有方法都是高度抽象,均未实现的方法。

接口里的实例域自动static final。接口镶嵌,所有接口都必须时public。如果是接口包含在某个类中,private的接口不能在类外implemented。

利用接口和工厂方法可以复用接口。如下:

class XX extends YY implements AA,BB,CC...NN
import static net.mindview.util.Print.*;
interface Game { boolean move(); }
interface GameFactory { Game getGame(); }
class Checkers implements Game {
private int moves = 0;
private static final int MOVES = 3;
public boolean move() {
print("Checkers move " + moves);
return ++moves != MOVES;
}
}
class CheckersFactory implements GameFactory {
public Game getGame() { return new Checkers(); }
}
class Chess implements Game {
private int moves = 0;
private static final int MOVES = 4;
public boolean move() {
print("Chess move " + moves);
return ++moves != MOVES;
}
}
class ChessFactory implements GameFactory {
public Game getGame() { return new Chess(); }
}
public class Games {
public static void playGame(GameFactory factory) {
Game s = factory.getGame();
while(s.move())
;
}
public static void main(String[] args) {
playGame(new CheckersFactory());
playGame(new ChessFactory());
}
} /* Output:
Checkers move 0
Checkers move 1
Checkers move 2
Chess move 0
Chess move 1
Chess move 2
Chess move 3
*///:~

猜你喜欢

转载自www.cnblogs.com/waytek/p/11121817.html