Java_多态性

3.7、多态性(重点)

         多态是面向对象的最后一个主要特征,它本身主要分为两个方面:

                   · 方法的多态性:重载与覆写

                            |- 重载:同一个方法名称,根据不同的参数类型及个数可以完成不同的功能;

                            |- 覆写:同一个方法,根据操作的子类不同,所完成的功能也不同。

                   · 对象的多态性:父子类对象的转换。

                            |- 向上转型:子类对象变为父类对象,格式:父类 父类对象 = 子类实例,自动;

                            |- 向下转型:父类对象变为子类对象,格式:子类 子类对象 = (子类) 父类实例,强制;

范例:编写一个简单的程序,观察程序输出

class A {

         public void print() {

                   System.out.println("A、public void print(){}") ;

         }

}

class B extends A {

         public void print() {   // 方法覆写

                   System.out.println("Bpublic void print(){}") ;

         }

}

public class Test {

         public static void main(String args[]) {

                   B b = new B() ;   // 实例化子类对象

                   b.print() ;

         }

}

         这种操作主要观察两点:

                   · 看new的是那一个类;

                   · 看new的这个类之中是否被覆写了父类要调用的方法。

范例:向上转型

public class Test {

         public static void main(String args[]) {

                   A a = new B() ;   // 向上转型

                   a.print() ;

         }

}

范例:向下转型

public class Test {

         public static void main(String args[]) {

                   A a = new B() ;  // 向上转型

                   B b = (B) a ;       // 向下转型

                   b.print() ;

         }

}

范例:观察如下程序

public class Test {

         public static void main(String args[]) {

                   A a = new A() ;  // 没有转型

                   B b = (B) a ;       // 向下转型,java.lang.ClassCastException: A cannot be cast to B

                   b.print() ;

         }

}

         以上的程序在编译的时候没有发生任何的错误信息,但是在执行的时候出现了“ClassCastException”错误提示,表示的是类转换异常,即:两个没有关系的类互相发生了对象的强制转型。

         在整个故事之中可以发现:

                   · 如果两个人真的有关系,可以分配遗产;

                   · 如果两个人真的没有关系,不能分配遗产。

转型因素:

         · 在实际的工作之中,对象的向上转型为主要使用,80%,向上转型之后,所有的方法以父类的方法为主,但是具体的实现,还是要看子类是否覆写了此方法;

         · 向下转型,10%,因为在进行向下转型操作之前,一定要首先发生向上转型,以建立两个对象之间的联系,如果没有这种联系,是不可能发生向下转型的,一旦发生了运行中就会出现“ClassCastException”,当需要调用子类自己特殊定义方法的时候,才需要向下转型;

         · 不转型,10%,在一些资源较少的时候,例如:移动开发。

class A {

         public void print() {

                   System.out.println("A、public void print(){}") ;

         }

}

class B extends A {

         public void print() {      // 方法覆写

                   System.out.println("B、public void print(){}") ;

         }

         public void getB() {

                   System.out.println("B、getB()") ;

         }

}

public class Test {

         public static void main(String args[]) {

                   A a = new B() ;   // 向上转型

                   B b = (B) a ;        // 向下转型

                   b.getB() ;    // 父类没有的操作,只能通过子类对象调用

         }

}

         既然在发生向下转型的操作之中会存在一些问题,那么能不能想判断一下再转型呢?如果要想判断某一个对象是否是某一个类的实例,只需要使用instanceof关键字即可,此操作的语法如下:

对象 instanceof 类  è 返回boolean型

范例:观察instanceof验证

public class Test {

         public static void main(String args[]) {

                   A a = new A() ;  

                   System.out.println(a instanceof A) ;

                   System.out.println(a instanceof B) ;

                   if (a instanceof B) {

                            B b = (B) a ;

                            b.getB() ;

                   }

         }

}

         为了日后的操作方便,在编写代码的时候,尽量不要去执行向下转型操作。子类尽量不要去扩充新的方法名称(父类没有的方法名称),依据父类定义的操作完善方法。

范例:观察完善的操作

class Person {

         private String name ;

         private int age ;

         public Person(String name,int age) {

                   this.name = name ;

                   this.age = age ;

         }

         public String getInfo() {

                   return "姓名:" + this.name + ",年龄:" + this.age ;

         }

}

class Student extends Person {       // Student类继承了Person类

         private String school ;   // 子类的属性

         public Student(String name,int age,String school) {

                   super(name,age) ;

                   this.school = school ;

         }

         public String getInfo() {

                   return super.getInfo() + ",学校:" + this.school ;

         }

}

public class TestDemo {

         public static void main(String args[]) {

                   Person per = new Student("张三",20,"清华大学") ;

                   System.out.println(per.getInfo()) ;

         }

}

         一切的操作标准都要以父类为主,这是向上转型的意义所在,另外,除了以上的意义之外,向上转型还可以解决一个最为麻烦的问题。例如:

class A {

         public void print() {

                   System.out.println("A、public void print(){}") ;

         }

}

         现在要求定义一个方法,这个方法可以接收A类的任意子类对象。

实现方式一:不使用对象转型

class A {

         public void print() {

                   System.out.println("A、public void print(){}") ;

         }

}

class B extends A {

         public void print() {      // 方法覆写

                   System.out.println("B、public void print(){}") ;

         }

}

class C extends A {

         public void print() {      // 方法覆写

                   System.out.println("C、public void print(){}") ;

         }

}

public class Test {

         public static void main(String args[]) {

                   fun(new B()) ;

                   fun(new C()) ;

         }

         public static void fun(B b) {

                   b.print() ;

         }

         public static void fun(C c) {

                   c.print() ;

         }

}

         但是,如果真的依靠了以上的方式进行代码开发的话,最为严重的事情:如果A类有5000W个子类,方法重载5000W次,并且一旦有新的子类产生,那么方法都要被重复的修改,这样不现实。

实现方式二:利用对象向上转型完成

public class Test {

         public static void main(String args[]) {

                   fun(new B()) ;

                   fun(new C()) ;

         }

         public static void fun(A a) {

                   a.print() ;

         }

}

         这样一来,参数的类型就得到了统一,就算有再多的子类出现,方法或者是类也不需要进行修改了,但是在这块必须强调的是:子类操作的过程之中,尽量向父类靠拢。

class A {

         public void print() {

                   System.out.println("A、public void print(){}") ;

         }

}

class B extends A {

         public void print() {      // 方法覆写

                   this.getB() ;

                   System.out.println("B、public void print(){}") ;

         }

         public void getB() {

                   System.out.println("B、getB()") ;

         }

}

class C extends A {

         public void print() {      // 方法覆写

                   this.getC() ;

                   System.out.println("C、public void print(){}") ;

         }

         public void getC() {

                   System.out.println("C、getC()") ;

         }

}

public class Test {

         public static void main(String args[]) {

                   fun(new B()) ;

                   fun(new C()) ;

         }

         public static void fun(A a) {

                   a.print() ;

         }

}

         以后所有的代码之中,都会存在对象的转型问题,并且向上转型居多。

         在日后的所有开发之中,像之前程序那样,一个类去继承另外一个已经实现好的类的情况,是不可能出现的。即:一个类不能去继承一个已经实现好的类,只能继承抽象类或实现接口。对于抽象类和接口如果要想真正的清楚其概念,需要一段很长的时间,今天讲解它们的基本语法、定义形式、使用方式,给出一些代码的结构。

原文地址:https://www.cnblogs.com/guwenren/p/3016536.html