Java面向对象(五):OOP三大特性之多态 — final 关键字

 

一、多态 

   定义:指允许不同子类的对象对父类同一消息能做出不同的响应。(重写父类的方法) 

   即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

1、面向对象的多态的实现前提:

(1)要有继承:类与类之间必须有继承关系;

(2)要有重写:子类重写父类的成员方法(可以不重写,但这就失去了多态的意义);

(3)向上转型:父类引用可以指向任何一个子类的对象。

2、向上转型(子类自动转为父类):子类"伪装"成父类,执行子类的方法;

class Fu { 

  ..... 

class Zi extends Fu {

   .....

      Fu  fu      =   new Zi();

父类  父类引用 =  子类对象 

注:

1、Java指向的两个时期:编译器与执行器,编译期看类型,执行期看对象。

2、多态调用函数的处理过程: 编译器从父类查找是否有该函数,没有的话报错,有的话在执行期执行子类中重写的同名函数,而不是父类。 

例程:duotai包:ZMS.java ZMSSON.java

3、向下转型(父类强制转化为子类):"伪装"成父类的"子类"还原成真正的子类

Zi zi = (Zi) fu; //类似于强制转换大范围到小范围 

例程:duotai包:ZMS.java ZMSSON.java

ZMS.java

 1 package duoTai;
 2 
 3 public class ZMS {
 4     String name;
 5     int age;
 6 
 7     public void teach() {
 8         
 9         System.out.println("我是父类ZMS教Java");
10     }
11     
12     public void show() {
13         System.out.println(name+age);
14         
15     }
16     
17 }
View Code

ZMSSON.java

 1 package duoTai;
 2 /**
 3  * 创建ZMS子类
 4  * 多态的测试
 5  * 
 6  * */
 7 public class ZMSSON extends ZMS {
 8     
 9     //重写父类中同名方法
10     public void teach() {
11         
12         System.out.println("我是ZMS子类教文学");
13     //    like();
14     }
15     
16     //子类自己的成员方法
17     public void like() {
18         System.out.println("ZMSSON喜欢踢球");
19         
20     }
21     
22     public static void main(String[] args) {
23     
24         /*
25          * 多态的表示:父类 父类引用名 = 子类对象
26          * 多态调用函数的处理过程: 编译器从父类查找是否有该函数,没有的话报错,
27          *                                                 有的话在执行期执行子类中重写的同名函数,而不是父类。
28          * 
29          * */
30         ZMS zmsText = new ZMSSON();
31         zmsText.teach();
32         
33         //调用不了父类没有的方法
34         //zmsText.like();
35     
36         //调用父类的成员变量方法
37         zmsText.name = "zms";
38         zmsText.age = 65;
39         zmsText.show();
40     
41         //
42         ZMSSON zmsSon = (ZMSSON) zmsText;
43         zmsSon.teach();
44         zmsSon.like();
45         
46     }
47     
48 }
View Code

4、多态的好处:

(1)提高了代码的复用性(继承)

(2)提高了代码的扩展性(多态)

5、instanceof 关键字:

      boolean b = a instanceof b;

      判断a类是否属于另一个b类,是返回true,否则返回false。

 练习:跟据从键盘输入数字不同选择不同的子类对象,执行不同的响应(重点理解);   

例程:duotai包:Animal.java duoTaiAnimal.java

创建父类:

 1 package duoTai;
 2 
 3 public class Animal {
 4     public String name ;
 5     public int age;
 6     
 7     public void eat() {
 8         System.out.println(name+"动物吃东西");
 9     }
10     
11 }
View Code

创建两个子类:

 1 package duoTai;
 2 
 3 public class Cat extends Animal{
 4     
 5     //重写父类方法
 6     public void eat() {
 7         System.out.println("猫吃鱼");
 8         
 9     }
10     
11     //写子类自己的方法
12     public void catchMouse() {
13         System.out.println("抓老鼠");
14     }
15     
16 }
17 
18 
19 // 在另一个java文件中创建
20 package duoTai;
21 
22 public class Dog extends Animal{
23         
24        //重写父类方法
25         public void eat() {
26             System.out.println("吃狗粮");
27         }
28         
29         //写子类自己的方法
30         public void kanMen() {
31             System.out.println("狗看门");
32         }
33 }
View Code

  创建测试功能类:  

 1 package duoTai;
 2 
 3 /**
 4  * @author  Kanekiyi
 5  * 理解多态的意义:同一消息(函数)可以根据发出的对象不同而产生不同的行为方式。
 6  *                          Or   不同的对象调用同一个函数能够产生不同的行为方式。
 7  */
 8 import java.util.Scanner;
 9 
10 public class duoTaiAnimal {
11     
12     @SuppressWarnings("resource")
13     public static void main(String[] args) {
14         
15         System.out.println("请输入数字1选择猫,数字2选择狗");
16         Scanner sc  = new Scanner(System.in);
17 
18         int num = sc.nextInt();
19         Animal animal = new Animal();
20         /*
21          * 向上转型时,根据指令选择不同的对象源
22          */
23         if (num == 1) {
24             animal = new Cat();
25         }    else if (num == 2) {
26             animal = new Dog();
27         }    else {
28             System.out.println("输入数字错误请重新输入数字1或者2");
29         }
30         
31         runAnimal ( animal);
32         
33     }
34     
35     public static  void runAnimal(Animal a) {
36         
37         //根据对象的不同执行子类重写的eat()方法;
38         a.eat();                                
39         
40         /*
41          * 向下转型时,注意转型目标子类类型是否符合
42          * 目的:执行子类中特有的功能
43          *          
44          */
45         
46         if (a instanceof Cat) {
47             Cat cat = (Cat) a;
48             cat.catchMouse();
49             
50         }    else if (a instanceof Dog) {
51             Dog dog = (Dog) a;                                    
52             dog.kanMen();
53             
54         }    else {
55             System.out.println("输入错误,不属于cat类也不属于Dog类");
56         }
57         
58     }
59 
60 }
View Code

二、final 关键字

2.1 final修饰类

  final修饰的类不能被继承;

2.2 final修饰变量

final 变量能被显式地初始化并且只能初始化一次。被声明为 final 的对象的引用不能指向不同的对象,但是 final 对象里的数据可以被改变。也就是说 final 对象的引用不能改变,但是里面的值可以改变。(存疑)。

final与static一起修饰成员变量构成常量,声明的时候常量名全部大写,可以直接通过类名访问。

例程:

 1 package Fianal;
 2 
 3 
 4 //public class Final1 extends Final0{        final修饰的类不能够被继承
 5 public class Final1 {
 6     
 7     int IDCard ;
 8      //final修饰的成员变量声明时初始化且有且只初始化一次。
 9     final int IDCardNum =314;         
10     final int IDCardNum1;                                 
11 
12     static final String IDCARD= "36452345245X";
13     
14     //通过构造函数给final修饰的成员变量初始化
15     public Final1() {
16         super();
17         IDCardNum1 =314; 
18         
19     }
20 
21     public final void textMath() {
22         
23         System.out.println("我是Final1类的final方法");
24     }
25     
26      
27 }
View Code

2.3 final 修饰方法

final 修饰成员方法,可以被子类继承,但是不能被重写;

注:

1、final 修饰的成员变量初始化的两种方式:

1) 声明时就初始化;

2)通过构造函数初始化。

且只初始化一次,初始化后就不能修改。

2、final 修饰的变量为常量时,在加载时系统会将变量替换为其所表示的常量。

例程:

 1 package Fianal;
 2 
 3 public class Final2 extends Final1 {
 4     
 5     //父类final修饰的成员方法不能重写,只能调用
 6     //public final void textMath() {}
 7     
 8     public static void main(String[] args) {
 9         Final2 textFinal = new Final2();
10         textFinal.IDCard = 2;
11         
12         //final修饰的变量在声明时就初始化且只能初始化一次,只能被调用不能被修改
13         //textFinal.IDCardNum = 3;
14         System.out.println("普通成员变量IDCard:"+textFinal.IDCard);
15         System.out.println("final修饰的成员变量IDCardNum:"+textFinal.IDCardNum);
16         //System.out.println("final和static修饰的成员变量IDCARD:"+textFinal.IDCARD);
17         //常量可以直接调用或类名调用
18         System.out.println("final和static修饰的成员变量IDCARD:"+Final1.IDCARD);
19         System.out.println("final和static修饰的成员变量IDCARD:"+IDCARD);
20 
21         textFinal.textMath();
22         
23     }
24     
25 }
View Code

 

猜你喜欢

转载自www.cnblogs.com/Kanekiyi/p/9508685.html