首页 > 代码库 > Java编程思想(五) —— 多态(下)

Java编程思想(五) —— 多态(下)

多态(上)基本讲解了很多多态的特性和问题。下面继续。


1)构造器和多态

这个问题其实前面写过了,构造器实际上是static方法,只不过是隐式声明,所以构造器并没有多态性。

但是需要知道加载的顺序。

class GrandFather{
    GrandFather(){
        print();
    }
   
    private int print(){
        System.out.println("g");
        return 1;
    }
}
class Father extends GrandFather{
    Father(){
        print();
    }
    private int print(){
        System.out.println("f");
        return 1;
    }
}
public class Son extends Father{
    Son(){
        print();
    }
    private  int print(){
        System.out.println("s");
        return 1;
    }
    public static void main(String[] args) {
        Son s = new Son();
    }
}

其实new出子类的时候,需要调用父类构造器,递归下去。

所以输出结果为g,f,s。


2)继承与清理

虽然有GC,但是书上还是用了一次引用技术的方法来模拟清理对象。

class Count{
    private int reference;
    private static int counter;
    private final long id = counter++;//注意一下,虽然是final,或许会觉得它不是不可变
    //为什么还给他赋值呢,对,但是现在值没确定,我们给他赋值之后就不会再变了。
    
    Count(){
        System.out.println("count"+id);
    }
    
    public void addReference(){
        reference ++;
    }
    
    protected void dispose(){
        if(--reference == 0){
            System.err.println("dispose count"+id);
        }   
    }
}

public class Rubbish {
    private Count count;
    private static int counter;
    private final long id = counter++;
    
    Rubbish(Count count){
        System.out.println("Rubbish"+id);
        this.count = count;
        this.count.addReference();
    }
    
   
    protected void dispose(){
        System.out.println("dispose Rubbish"+id);
        count.dispose();
    }
    
    public static void main(String[] args) {
        Count count = new Count();
        Rubbish rubbish[] = {new Rubbish(count),new Rubbish(count),
                new Rubbish(count),new Rubbish(count)};
        for(Rubbish r:rubbish){
            r.dispose();
        }
    }
}

每new一个对象的时候,计数器counter计算count对象的数量,id为final是我们确定之后不希望被改变,reference是引用计数,每每对象增加一个,便会加一,当引用都没有的时候,我们也要将计算引用的这个对象清理。

原来GC里面的引用计数法是这样的一个原理。


3)用继承进行设计

TV大变身:

class TV{
    public  String getString(){
        return "tv";
    }

    public TV change() {
        // TODO Auto-generated method stub
        return new TV();
    }
}
class SanTV extends TV{
    public  String getString(){
        return "santv";
    }
}
public class LeTV extends TV{
    public String getString(){
        return "letv";
    }
    public SanTV change(){
        return new SanTV();
    }
    public static void main(String[] args) {
        TV letv = new LeTV();
        System.out.println(letv.getString());
        TV newtv = letv.change();
        System.out.println(newtv.getString());
    }
}

之前犯了一个错误,TV类里面是没有change方法的,我直接用了

TV newtv = letv.change();
发现报错,TV没有定义change方法,我子类不是可以有自己的新方法吗,为什么会报错?

后面搞明白了,父类引用指向子类对象,其实一开始调用的是父类的方法,由于多态的存在,后期绑定之后,才会结合具体的重写方法。但是我现在父类方法都没定义,肯定报错。为了验证,修改代码。

public class LeTV extends TV{
    public String getString(){
        return "letv";
    }
    public static void main(String[] args) {
        TV letv = new LeTV();
        System.out.println(letv.getString());
        TV newtv = letv.change();
        System.out.println(newtv.getString());
    }
}

现在子类没有重写change方法,默认就是继承父类的change方法,这样的输出结果就是letv,tv。


其实上面这种转换是一种特殊的模式——状态模式。

其实TV可以看成List,两个具体的TV可以看成LinkedList和ArrayList。两种状态可以灵活的切换。


多态就讲到这里了——不同的形式。

要真正的理解,实需多敲敲代码,写完之后自己会发现自己是用了多态。

Java编程思想(五) —— 多态(下)