zoukankan      html  css  js  c++  java
  • Java基础-面向对象第三大特性之多态(polymorphism )

                    Java基础-面向对象第三大特性之多态(polymorphism )

                                          作者:尹正杰

    版权声明:原创作品,谢绝转载!否则将追究法律责任。

    一.多态概述

      多态是继封装,继承之后,面向对象的第三大特性,多态的前提是继承。

      从现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三即是学生也是人。即出现两种形态。Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

      最终多态体现为父类引用变量可以指向子类对象。多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。

    二.多态调用的三种形式

      多态调用方法,方法必须运行子类的重写!

    1>.多态的定义格式:就是父类的引用变量指向子类对象。

    1 父类类型  变量名 = new 子类类型();
    2 变量名.方法名();

    2>.普通类多态定义的格式

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 class Father{
     8     public void show(){
     9         System.out.println("父类的show方法!");
    10     }
    11 }
    12 
    13 class Son extends Father{
    14     public void show(){
    15         System.out.println("子类重写父类的show方法!");
    16     }
    17 }
    18 
    19 public class MyInterfaceDemo{
    20     public static void main(String[] args){
    21         //Java中,对象的多态性,调用公式:“父类类型或者接口类型  变量  =  new 子类对象();”
    22         Father f = new Son();
    23         f.show();
    24     }
    25 }
    26 
    27 
    28 
    29 /*
    30 以上代码执行结果如下:
    31 子类重写父类的show方法!
    32 */

    3>.抽象类多态定义的格式

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 abstract class Father{
     8     public abstract void eat();
     9 }
    10 
    11 class Son extends Father{
    12     public void eat(){
    13         System.out.println("儿子喜欢吃米饭!");
    14     }
    15 }
    16 
    17 public class MyInterfaceDemo{
    18     public static void main(String[] args){
    19         //抽象类Father,子类是Son
    20         Father f = new Son();
    21         f.eat();
    22     }
    23 }
    24 
    25 
    26 
    27 /*
    28 以上代码执行结果如下:
    29 儿子喜欢吃米饭!
    30 */

    4>.接口多态定义格式

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 interface  Father{
     8     public abstract void smoking();
     9 }
    10 
    11 class Son implements Father{
    12     public void smoking(){
    13         System.out.println("儿子会抽烟!");
    14     }
    15 }
    16 
    17 public class MyInterfaceDemo{
    18     public static void main(String[] args){
    19         //接口Father,实现类Son
    20         Father f = new Son();
    21         f.smoking();
    22     }
    23 }
    24 
    25 
    26 
    27 /*
    28 以上代码执行结果如下:
    29 儿子会抽烟!
    30 */

    三.多态中成员变量的特点

    1>.成员变量(编译运行全看父类)

      a>.编译的时候,参考父类中有没有这个变量,如果有,编译成功,没有则编译失败;

      b>.运行的时候,运行的是父类中的变量值;

    2>.成员方法(编译看父类,运行看子类

      a>.编译的时候,参考父类中有没有这个方法,如果有,编译成功,没有则编译失败

      b>.运行的时候,运行的是子类的重写方法;

    3>.静态成员方法

      没有多态性。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 class  Father{
     8     int age = 30;
     9     public void show(){
    10         System.out.println("Father的方法");
    11     }
    12 }
    13 
    14 class Son extends Father{
    15     int age = 8;
    16     public void show(){
    17         System.out.println("Son的方法");
    18     }
    19 }
    20 
    21 public class MyInterfaceDemo{
    22     public static void main(String[] args){
    23         Father f = new Son();
    24         System.out.println(f.age);
    25         f.show();
    26     }
    27 }
    28 
    29 
    30 
    31 /*
    32 以上代码执行结果如下:
    33 30
    34 Son的方法
    35 */

    四.instanceof关键字

       我们了解多态之后,会发现一个对象的数据类型不一定会保持不变。当我们想要确定一个对象是否是某个类时,就会用到比较运算符,只不过它很特殊,不能赢大于小于或是等于号直接进行判断,而是要用到关键字,即instanceof,它只能用作比较引用数据类型,用来比较一个引用类型的变量,是不是这个类型的对象。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6  
     7 abstract class Person{
     8     public abstract void sleep();
     9 }
    10 
    11 
    12 class Student extends Person{
    13     public void sleep(){
    14         System.out.println("学生在休息!");
    15     }
    16 }
    17 
    18 class Teacher extends Person{
    19     public void sleep(){
    20         System.out.println("老师在休息!");
    21     }
    22 }
    23 
    24 public class PersonDemo{
    25     public static void main(String[] args){
    26         
    27         Person p = new Student();
    28         
    29         p = new Teacher();
    30         
    31         boolean flag = p instanceof Student;
    32         
    33         System.out.println("引用数据类型'p'是否为Student类型:>>> " + flag);
    34     
    35         p.sleep();
    36     }
    37 }
    38 
    39 
    40 
    41 
    42 /*
    43 以上代码执行结果如下:
    44 引用数据类型'p'是否为Student类型:>>> false
    45 老师在休息!
    46 */

    五.多态转型

    1>.多态的向上转型

       多态常见的就是自动类型提升,将取值范围小的,自动提升为取值范围大的。范围小的,看成是子类,范围大的看成父类。

    优点:

      这样做的好出就是可以调用子类父类的公共属性(方法)。

    缺点:

      无法调用子类特有的属性(方法)。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6  
     7 abstract class Person{
     8     public abstract void sleep();
     9 }
    10 
    11 
    12 class Student extends Person{
    13     public void sleep(){
    14         System.out.println("学生在休息!");
    15     }
    16 }
    17 
    18 class Teacher extends Person{
    19     public void sleep(){
    20         System.out.println("老师在休息!");
    21     }
    22 }
    23 
    24 public class PersonDemo{
    25     public static void main(String[] args){
    26         
    27         //从子类对象往父类变量赋值(自动类型提升,向上转型)
    28         Person p = new Student();
    29         
    30     }
    31 }

    2>.多态的向下转型

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6  
     7 abstract class Person{
     8     public abstract void sleep();
     9 }
    10 
    11 
    12 class Student extends Person{
    13     public void sleep(){
    14         System.out.println("学生在休息!");
    15     }
    16 }
    17 
    18 class Teacher extends Person{
    19     public void sleep(){
    20         System.out.println("老师在休息!");
    21     }
    22 }
    23 
    24 public class PersonDemo{
    25     public static void main(String[] args){
    26         
    27         //从子类对象往父类变量赋值(自动类型提升,向上转型)
    28         Person p = new Student();
    29         
    30         
    31         //从父类类型转向子类类型(向下转型)
    32         Student s  = (Student)p; 
    33 
    34     }
    35 }

    3>.多态转型的案例

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 abstract class Animal{
     8     public abstract void eat();
     9 }
    10 
    11 class Cat extends Animal{
    12     public void eat(){
    13         System.out.println("猫吃猫粮!");
    14     }
    15     
    16     public void catchMouse(){
    17         System.out.println("猫抓老鼠!");
    18     }
    19 }
    20 
    21 class Dog extends Animal{
    22     public void eat(){
    23         System.out.println("狗吃狗粮!");
    24     }
    25     
    26     public void run(){
    27         System.out.println("狗能跑!");
    28     }
    29 }
    30 
    31 public class AnimalDemo{
    32     public static void main(String[] args){
    33         //两个子类,使用两次多态调用
    34         Animal a1 = new Cat();
    35         Animal a2 = new Dog();
    36         //a1,a2调用子类父类共有方法,运行走子类的重写方法
    37         a1.eat();
    38         a2.eat();
    39         /*类型向下转型,强制转换,调用子类的特有,防止发生异常,
    40         a1属于CatUI小,转成Cat类,a2属于Dog对象,转成Dog类,我们
    41         可以用关键字instanceof判断。
    42         */
    43         if(a1 instanceof Cat){
    44             Cat c = (Cat)a1;
    45             c.catchMouse();
    46         }
    47         
    48         if(a2 instanceof Dog){
    49             Dog d = (Dog)a2;
    50             d.run();
    51         }
    52         
    53     }
    54 }
    55 
    56 
    57 /*
    58 以上代码执行结果如下:
    59 猫吃猫粮!
    60 狗吃狗粮!
    61 猫抓老鼠!
    62 狗能跑!
    63 */

    六.匿名对象

    1>.匿名对象的概念   

      匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6  
     7 class Person{
     8     public void eat(){
     9         System.out.println("人是铁,饭是钢,一顿不吃饿得慌!");
    10     }
    11 }
    12 
    13 
    14 public class PersonDemo{
    15     public static void main(String[] args){
    16         
    17         //有名字的对象,引用类型变量,可以反复使用eat方法。
    18         Person p = new Person();
    19         p.eat();
    20         
    21         //匿名对象,没有引用变量,只能使用一次,如果你再通过new调用eat方法的话实际上是又新生成了一个对象。
    22         new Person().eat();
    23         new Person().eat();
    24         
    25     }
    26 }

    2>.匿名对象的特点

      a>.创建匿名对象直接使用,没有变量名;

      b>.匿名对象在没有指定其引用变量时,只能使用一次;

      c>.匿名对象可以作为方法接受的参数,方法返回值使用;

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6  
     7 class Person{
     8     public void eat(){
     9         System.out.println("人是铁,饭是钢,一顿不吃饿得慌!");
    10     }
    11 }
    12 public class PersonDemo{
    13     public static void main(String[] args){
    14         //有名字的对象,引用类型变量,可以反复使用eat方法。
    15         Person p = new Person();
    16         p.eat();
    17         //匿名对象,没有引用变量,只能使用一次,如果你再通过new调用eat方法的话实际上是又新生成了一个对象。
    18         new Person().eat();
    19         new Person().eat();
    20         method(p);
    21         
    22         //匿名方法当实参
    23         method(new Person());        
    24         p = method();
    25         method(p);
    26     }
    27     //方法的返回值是Person类型,方法的return语句,返回的是这个类的对象。就可以用匿名对象来实现。
    28     public static Person method(){
    29         return new Person();
    30     }
    31     //调用方法method,传递Person类型对象
    32     public static void method(Person p){
    33         p.eat();
    34     }
    35 }
    36 
    37 
    38 
    39 /*
    40 以上代码执行结果如下:
    41 人是铁,饭是钢,一顿不吃饿得慌!
    42 人是铁,饭是钢,一顿不吃饿得慌!
    43 人是铁,饭是钢,一顿不吃饿得慌!
    44 人是铁,饭是钢,一顿不吃饿得慌!
    45 人是铁,饭是钢,一顿不吃饿得慌!
    46 人是铁,饭是钢,一顿不吃饿得慌!
    47 */

    七.内部类

    1>.内部类概念

      a>.什么是内部类

        将类写在其它类的内部,可以写在其它类的成员位置和局部位置,这时写在其它类内部的类成为内部类,其它类也称为外部类。

      b>.什么时候使用内部类

        在描述事物时,若一个事物内部还包含其它可能包含的事物,比如在描述汽车时,汽车中还包含这发动机,这时发动机就可以使用内部类来描述。

      c>.内部类分类

        内部类分为成员内部类和局部内部类。我们定义内部类时,就是一个正常定义类的过程,同样包含各种修饰符,继承与实现关系等。在内部类中可以直接访问外部类的所有成员。

    2>.成员内部类的调用格式

      内部类可以使用外部类成员,包括私有变量。外部类要使用内部类的成员,必须建立内部类对象。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 class Outer{
     8     private int a = 100;
     9     class Inner{
    10         public void inner(){
    11             System.out.println("内部类方法inter " + a);
    12         }
    13     }
    14 }
    15 
    16 public class InnerClassDemo{
    17     public static void main(String[] args){
    18         //创建内部类对象in
    19         Outer.Inner  in = new Outer().new Inner();
    20         //调用内部类方法
    21         in.inner();
    22     }
    23 }
    24 
    25 
    26 /*
    27 以上代码执行结果如下:
    28 内部类方法inter 100
    29 */

    3>.成员内部类的同名变量调用

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 class Outer{
     8     int a = 100;
     9     class Inner{
    10         int a = 200;
    11         public void inner(){
    12             int a = 300;
    13             System.out.println("内部类局部变量(内部类成员方法)访问:>>> "+ a);
    14             System.out.println("内部类成员变量访问:>>> "+ this.a);
    15             System.out.println("外部类成员变量访问:>>> "+ Outer.this.a);
    16         }
    17     }
    18 }
    19 
    20 public class InnerClassDemo{
    21     public static void main(String[] args){
    22         //创建内部类对象in
    23         Outer.Inner  in = new Outer().new Inner();
    24         //调用内部类方法
    25         in.inner();
    26     }
    27 }
    28 
    29 
    30 /*
    31 以上代码执行结果如下:
    32 内部类局部变量(内部类成员方法)访问:>>> 300
    33 内部类成员变量访问:>>> 200
    34 外部类成员变量访问:>>> 100
    35 */

    3>.局部内部类

      局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 class Outer{
     8     public void out(){
     9         class Inner{
    10             public void inner(){
    11                 System.out.println("局部内部类方法!");
    12             }
    13         }
    14         //创建我们定义的Inner对象
    15         Inner in = new Inner();        
    16         //调用创建好的对象的方法,这样不管谁只要能调用out方法就会触发调用Inner类中的inner()方法啦!
    17         in.inner();
    18     }
    19 }
    20 
    21 public class InnerClassDemo{
    22     public static void main(String[] args){
    23         new Outer().out();
    24     }
    25 }
    26 
    27 
    28 /*
    29 以上代码执行结果如下:
    30 局部内部类方法!
    31 */

    4>.匿名内部类

      a>.匿名内部类概念

        内部类是为了应对更为复杂的类间关系。查看源代码中会涉及到,而在日常业务中很难遇到,这里不做赘述。最长用到的内部类就是匿名内部类,它是局部内部类的一种。定义的匿名内部类有两个含义:第一,临时定义某一指定类型的子类;第二,定义后即刻创建刚刚定义的这个子类的对象。

      b>.定义匿名内部类的作用与格式

        匿名内部类是创建某个子类对象的快捷方式。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 
     7 interface  Smoking{
     8     public abstract void smoking();
     9 }
    10 
    11 public class  SmokingDemo{
    12     public static void main(String[] args){
    13         //这就是用匿名对象实现接口并调用接口中的方法,切记不要忘记调用smoking()了哟!
    14         new Smoking(){
    15             public void smoking(){
    16                 System.out.println("运维不喜欢吸烟!");
    17             }
    18         }.smoking();
    19     }
    20 }
    21 
    22 /*
    23 以上代码执行结果如下:
    24 运维不喜欢吸烟!
    25 */
  • 相关阅读:
    博弈论--sg函数
    博弈论--nim博弈
    dp--bitset优化
    树--欧拉序
    树--dfs序
    树--dsu on tree
    树--树的重心
    单调队列
    单调栈
    dp--背包
  • 原文地址:https://www.cnblogs.com/yinzhengjie/p/8811327.html
Copyright © 2011-2022 走看看