定义
如果B类是A类的子类或间接子类,当用B类创建对象b并将这个对象b的引用赋给A类对象a时,如:
A a= new B();
//OR
B b = new B(); A a = b;
则称A类对象a是子类B对象b的上转型对象。
注意
1,A既可以是一般class,还可以是interface、abstract(可以参考文章:抽象类和接口的功能与区别);
2,上转型对象不能调用子类新增的属性和方法,只能调用子类继承和隐藏的属性,子类继承和重写的方法;
解释—— 属性:子类中与父类同名的属性也算作子类新增属性,不能被调用。所以我们在程序中显示调用的那个同名属性事实上是属于父类的被隐藏属性,输出值当然会是父类的值。
方法—— 上转型对象调用的方法,要么是直接从父类那继承未被重写的方法,要么是被子类重写过的方法,不可能是隐藏方法。
3,尽管2中说明上转型对象不能调用子类新增的属性和方法,但是上转型对象可以通过子类重写的方法操作子类以及父类中的所有方法和属性 (不管新增还是隐藏);
4,上转型对象相对于子类对象,功能被弱化,但是能够强制转化为子类对象,从而具备子类的所有方法与属性 `B b=(B)a`;
5,子类对象实例被上转为父类对象,之所以还能够通过重写方法间接操作子类新增的方法与属性,是因为这个对象实例在内存中的本质还是子类类型的,只不过它的能力临时被消弱了;
6,强制转化后的子类对象尽管功能较上转型对象增强,但是无论通过“==”还是“equals()”,比较结果都为true,因为他们的引用(指向的内存首地址)是相等的,即他们指向同一内存地址中的对象实例;
7,Static静态方法属于类,能够被继承不能被重写;
8,OOP遵守里氏代换原则——基类所出现的任何位置,子类都能出现;
实例
父类:
public class Subject{
public String b="我是父类b";
public void other(){
System.out.println("我是父类没被重写的方法");
}
public static void statics(){
System.out.println("我是父类的静态方法");
}
public void operation(){
System.out.println("我是父类方法");
};
}
public class MySubject extends Subject {
public String a="我是子类新增a";
public String b="我是子类b";
@Override
public void operation() {
System.out.println("我是子类方法");
System.out.println(b);
System.out.println(super.b);
System.out.println(getB1());
System.out.println(getB2());
}
public String getA(){
return a;
}
public void setA(String a){
this.a=a;
}
public String getB1(){
return this.b;
}
public String getB2(){
return super.b;
}
public void setB1(String b){
this.b=b;
}
public void setB2(String b){
super.b=b;
}
}
验证
测试类:
public class ObserverTest {
public static void main(String[] args) {
Subject sub=new MySubject();
sub.operation();
MySubject sub1=(MySubject)sub;
System.out.println(sub1==sub);//true
System.out.println(sub1.equals(sub));//true
}
}
测试结果:
我是子类方法
我是子类b
我是父类b
我是子类b
我是父类b
true
true
另外:编译器提示:
还能看到,如果我们通过@override强制重写父类的static静态方法