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