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 }
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 }
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 }
创建两个子类:
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 }
创建测试功能类:
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 }
二、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 }
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 }
上一篇: C#面向对象之三大特性: 封装
下一篇: 压力山大