多态(上)基本讲解了很多多态的特性和问题。下面继续。
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。两种状态可以灵活的切换。
多态就讲到这里了——不同的形式。
要真正的理解,实需多敲敲代码,写完之后自己会发现自己是用了多态。
时间: 2024-11-08 21:38:35