class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){ //子类重新定义的自己独有的方法
System.out.println("B --> public void fun3(){}") ;
}
};
public class PolDemo01{
public static void main(String asrgs[]){
B b = new B() ; // 实例化子类对象
A a = b ; // 向上转型关系
a.fun1() ; // 此方法被子类覆写过
a.fun3() ;
}
};
这里a.fun3();这句代码就会报错,因为a已经是从b向上转型过来的了,它看不到b独有的方法了,能看到的都是b中从a继承而来和覆写而来的方法和属性。
但是,注意,发生了向上转型,是父类对象,然后去调用那些父类中的方法,会发现,被调用的依然是子类中覆写过的方法,如果没有覆写过这些方法,则才会调用父类中的方法,因为发生向上转型了,一定程度上说,他还是子类实例,在我的理解里,是剥除了子类独有特性的子类。(可以形象的这么理解,这个子类对象是个私生子,是婢女所生的非正室所生的孩子,没有给予他开疆拓土成为一方诸侯的能力,仅仅是拥有其父辈积攒的余荫以及和父辈紧密相关的权力,只有正室所生的孩子才拥有父辈带来的光辉以及在父辈基础上继续开疆拓土的权力)调用子类独有的方法和属性就会报错了,因为他的这些方法属性,已经被剥除了,他看不到了,所有报错了。
public class PolDemo01{
public static void main(String asrgs[]){
B b = new B() ; // 实例化子类对象
A a = b ; // 向上转型关系
a.fun1() ; // 此方法被子类覆写过
a.fun2() ;
}
};
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
public class PolDemo02{
public static void main(String asrgs[]){
A a = new B() ; // 向上转型关系
B b = (B)a ; // 发生了向下转型关系
b.fun1() ;
b.fun2() ;
b.fun3() ;
}
};
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
public class PolDemo03{
public static void main(String asrgs[]){
A a = new A() ; // 实例化了一个父类对象
B b = (B)a ; // 发生了向下转型关系
b.fun1() ;
b.fun2() ;
b.fun3() ;
}
};
首先不使用多态,这个问题,肯定需要使用重载来完成:
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("C --> public void fun1(){}") ;
}
public void fun5(){
System.out.println("C --> public void fun5(){}") ;
}
};
public class PolDemo04{
public static void main(String asrgs[]){
fun(new B()) ; // 传递B的实例
fun(new C()) ; // 传递B的实例
}
public static void fun(B b){
b.fun1() ; // 调用覆写父类中的fun1()方法
}
public static void fun(C c){
c.fun1() ; // 调用覆写父类中的fun1()方法
}
};
如果现在扩展功能,A类,有1000个子类,那就麻烦了,要增加很多个重载的功能方法,很不好。
使用对象的多态
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("C --> public void fun1(){}") ;
}
public void fun5(){
System.out.println("C --> public void fun5(){}") ;
}
};
public class PolDemo05{
public static void main(String asrgs[]){
fun(new B()) ; // 传递B的实例
fun(new C()) ; // 传递B的实例
}
public static void fun(A a){
a.fun1() ; // 调用覆写父类中的fun1()方法
}
};
这样的代码,无论A类有多少个子类都没问题。这个功能方法不需要进行修改。
其实对于这个问题,很简单,在Java中,可以通过instanceof关键字来判断,一个对象是哪一个类的实例。
对于之前的问题:一个方法可以接受一个类的任意子类对象,并可以调用该方法的问题已经通过多态的向上转型得到了完美的解决;那么现在有一个新的问题:A的子类A extends B,继承了A的方法,同时自定义了一个新的方法fun3(),A extends C,自定义了一个新的方法fun5(),现在的需求是:——当传入的类的类的对象是B的实例的时候,让这个对象调用fun3,如果传入的对象是C的实例的时候就让它调用fun5,
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
public class InstanceofDemo01{
public static void main(String asrgs[]){
A a1 = new B() ; // 通过向上转型实例化对象
System.out.println("A a1 = new B():" + (a1 instanceof A)) ; //true
System.out.println("A a1 = new B():" + (a1 instanceof B)) ; //true
A a2 = new A() ; // 通过向上转型实例化对象
System.out.println("A a2 = new A():" + (a2 instanceof A)) ; //true
System.out.println("A a2 = new A():" + (a2 instanceof B)) ; //FALSE
}
};
在开发中,对于向下转型,一定要进行转型验证,以避免classCastException。
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("C --> public void fun1(){}") ;
}
public void fun5(){
System.out.println("C --> public void fun5(){}") ;
}
};
public class InstanceofDemo02{
public static void main(String asrgs[]){
fun(new B()) ;
fun(new C()) ;
}
public static void fun(A a){
a.fun1() ;
if(a instanceof B){
B b = (B) a ;
b.fun3() ;
}
if(a instanceof C){
C c = (C) a ;
c.fun5() ;
}
}
};
如果现在要新增子类,则肯定要修改fun方法,这样一来就失去了程序的灵活性,
所以,开发中,程序设计的重点要放在父类的设计上,只有父类设计的足够合理,
开发过程才会非常方便,就想基石必须夯实,高楼才能更高。
开发规则:
一个类永远不要去继承一个已经实现好的类,而是最好去继承一个抽象类或者去实现一个接口。