• 1. 继承与多态教材第5章 继承 多态 方法的重载 包及其使用 接口
  • 2. 继 承继承是面向对象程序设计中两个类之间的一种关系。当一个类获取另一个类中所有非私有的数据和操作的定义作为自己的部分和全部成分的时候,称这两个类具有继承关系。 被继承的已有类称为父类或超类,派生出的新类称为已有类的子类。 继承分类: 单重继承:一个类只能有一个父类(Java、C#) 多重继承:一个类可以有多个父类(C++)
  • 3. 继 承子类继承父类: 父类中的非私有域不需要再定义; 父类中的非私有方法不需要再重新编写。 子类继承父类的非私有域和方法,还可以定义新的域和方法,改写父类的方法。 子类是在父类的基础上,做一些个性化的定义。 继承的优点: 使得程序结构清晰,明确类之间的关系; 提高开发效率,降低编码和维护的工作量。
  • 4. 类的继承树
  • 5. 类的继承树图形三维图形二维图形圆形三角形矩形正方形圆锥体球体立方体
  • 6. 派 生 子 类派生子类定义 [修饰符] class 类名 extends 父类名 [ implements 接口名(,接口名 …)] { 类体 } 子类继承了所有父类的非私有属性 (域和方法)作为自己的成员。 父类子类继承 extends
  • 7. 派 生 子 类例5-1 PhoneCard 类及其派生子类 abstract class PhoneCard{ double balance; abstract boolean performDial(); double getBalance(){ return balance;} } abstract class None_Number_PhoneCard extends PhoneCard{ String phoneSetType; String getSetType(){ return phoneSetType;} }
  • 8. 派 生 子 类例5-1 PhoneCard 类及其派生子类 abstract class Number_PhoneCard extends PhoneCard{ long cardNumber; int password; String connectNumber; boolean connected; boolean performConnection(long cn,int pw){ if(cn==cardNumber && pw==password){ connected=true; return true; } else return false; } }
  • 9. 派 生 子 类例5-1 PhoneCard 类及其派生子类class magCard extends None_Number_PhoneCard{ String usefulArea; boolean performDial() { if(balance>0.9){ balance- =0.9; return true; } else return false; } }class D200_Card extends Number_PhoneCard{ double additoryFee; boolean performDial() { if(balance>(0.5+additoryFee)) { balance-=(0.5+additoryFee); return true; } else return false; } }
  • 10. 域 的 继 承子类继承(拥用)父类的所有非私有域 PhoneCard类 balance None_Number_PhoneCard类 balance, phoneSetType Number_PhoneCard类 balance, cardNumber, password, connectNumber, connect MagCard类 balance, phoneSetType, usefulArea D200_Card类 balance, cardNumber, password, connectNumber connect,additoryFee
  • 11. 域 的 隐 藏子类重新定义一个与从父类继承来的域变量完全同名的变量(可以具有不同类型),称为域的隐藏,即子类新定义的域隐藏了父类的同名变量。 从父类继承的域变得不可见,子类的方法所操作的是子类自己定义的变量; 被隐藏的父类域在子类对象中仍占有独立的内存空间,子类可通过继承自父类的方法访问或处理继承自父类的域。 域 的隐 藏
  • 12. 例5-2 TestHiddenField.java abstract class PhoneCard{ double balance; abstract boolean performDial(); double getBalance(){…} } abstract class Number_PhoneCard extends PhoneCard{ long cardNumber; int password; String connectNumber; boolean connected; boolean performConnection(long cn,int pw){ … } } 域 的隐 藏
  • 13. 例5-2 TestHiddenField.java class D200_Card extends Number_PhoneCard{ double additoryFee; double balance; boolean performDial(){…} } public class TestHiddenField{ public static void main(String[] args) { D200_Card my200=new D200_Card(); my200.balance=50.0; System.out.println(“…"+my200.getBalance()); if(my200.performDial()) System.out.println(“…"+my200.balance); } } 域 的隐 藏
  • 14. 方法的继承定义:子类继承了父类的所有非私有方法; PhoneCard类 abstract boolean performDial(); double getBalance() Number_PhoneCard类 abstract boolean performDial(); double getBalance(); boolean performConnection(long cn, int pw) D200_Card类 boolean performDial(); double getBalance(); boolean performConnection(long cn, int pw); boolean performDial()
  • 15. 方法的覆盖定义:子类重新定义与父类方法里同名的非静态方法(要求方法名、返回值和参数列表完全相同) 被覆盖的父类方法将不会在子类对象中占有独立的内存空间。 如果子类的非抽象方法覆盖了父类的抽象方法,称子类“实现”了父类的抽象方法。
  • 16. 例5-3 TestOverLoad.java abstract class PhoneCard{ double balance; abstract boolean performDial(); double getBalance(){ return balance;} } abstract class Number_PhoneCard extends PhoneCard{ long cardNumber; int password; String connectNumber; boolean connected; boolean performConnection(long cn,int pw){ … } } 方法的覆盖
  • 17. 例5-3 TestOverLoad.java class D200_Card extends Number_PhoneCard{ double additoryFee; double balance; boolean performDial(){ … } double getBalance(){ return balance;} } public class TestOverLoad{ public static void main(String[] args) { D200_Card my200=new D200_Card(); my200.balance=50.0; System.out.println(“…"+my200.getBalance()); if(my200.performDial()) System.out.println(“…"+my200.balance); } } 方法的覆盖
  • 18. 例:TestHideOverLoad.java class Point { // 父类 int x = 0, y = 0 ; void move(int dx, int dy) { x += dx ; y += dy ; } } class RealPoint extends Point { // 子类 float x = 0.0f, y = 0.0f ; void move(int dx, int dy) { System.out.println("subclass's move"); move((float)dx, (float)dy); } void move(float dx, float dy){ x += dx; y += dy; } }
  • 19. public class TestHideOverLoad{ public static void main(String[] args) { RealPoint rp = new RealPoint(); System.out.println("x:" + rp.x + " y:" + rp.y); rp.move(1,1); System.out.println("x:" + rp.x + " y:" + rp.y); } }
  • 20. this含义:当前对象的引用,表示当前对象本身,在本类中使用. 作用: 1)调用当前对象的方法或域; 如:class Point { int x = 0, y = 0 ; void move(int x, int y) { this.x += x ; this.y += y ; } } 2)作为参数传递给其他对象或方法 如: input.addActionListener(this ) ;
  • 21. 例5-5 TestThis.java class Leaf{ private int i=0; Leaf (int i){this.i=i;} Leaf increament(){ i++; return this; } void print(){ System.out.println("i= "+i); } } public class TestThis{ public static void main(String [] args){ Leaf myLeaf=new Leaf(100); myLeaf.increament().increament().print();} }this
  • 22. 含义:对当前对象的父类对象的引用,在本类中使用. 作用: 1)在构造函数定义中用 super(参数列表) 调用父类的构造函数; 2)用super . 域名引用父类的域.super
  • 23. Super例5-6 TestSuper.java abstract class PhoneCard{ double balance; abstract boolean performDial(); double getBalance(){ return balance;} } abstract class Number_PhoneCard extends PhoneCard{ long cardNumber; int password; String connectNumber; boolean connected; boolean performConnection(long cn,int pw){ … } }
  • 24. Super例5-6 TestSuper.java class D200_Card extends Number_PhoneCard{ double additoryFee; double balance; boolean performDial(){ … } double getBalance(){ return super.balance;} } public class TestSuper{ public static void main(String[] args) { D200_Card my200=new D200_Card(); my200.balance=50.0; System.out.println(“…"+my200.getBalance()); if(my200.performDial()) System.out.println(“…"+my200.balance); } }
  • 25. 引例:函数功能:对任意的数据类型取绝对值(每一种类型对应一个函数) 整数: int i_abs(int i); 单精度: float f_abs(float f); 双精度: double d_abs(double d); 面向对象: Math.abs( int i ); Math.abs( float f ); Math.abs( double d );多 态
  • 26. 多 态定义:同一个行为具有多个不同表现形式或形态。 作用:提高程序的抽象度、简洁性,有益于程序进行扩展。 主要实现方式: 方法的覆盖(不同类) 方法的重载(同一类) 对像的引用,子类的对象作为父类来看待。
  • 27. 方法覆盖含义:定义与父类完全相同的方法,实现对父类方法的覆盖: 完全相同的方法名; 完全相同的参数列表; 完全相同类型的返回值。 注意: 三个条件有一个不满足,就不是方法的覆盖,而是子类自己定义与父类无关的方法,父类的方法未被覆盖,因而仍然存在; 如果子类的非抽象方法覆盖了父类的抽象方法,称子类实现了父类的抽象方法。
  • 28. 含义:在同类中用同一个名字来表示不同的方法。 方法名必须相同(是同一类中定义的同名方法) 方法的参数必须不同。同名不同方法是靠不同形式的参数列表来区分,形式参数的个数、类型、顺序之一不同就可以区分。 注意:同名方法同参数但是返回类型不同语法出错,更不是重载的标志。 作用:由于在完成同一功能时,可能有不同的具体情况,所以需要定义含不同具体内容的方法,利用“重名”现象提高程序的抽象度和简洁性。方法的重载
  • 29. 方法的重载例:(相同类型的工作,不同的参数) public void println(int i) public void println(float f) public void println(String s) Integer类的方法重载例: String toString() static String toString(int i) static String toString(int i , int radix) Double 类的方法重载例: String toString() static String toString(double d)System.out.println(…)
  • 30. 方法重载例例5-10 TestOverride.java abstract class PhoneCard{ double balance; abstract boolean performDial(); double getBalance(){ return balance;} } abstract class Number_PhoneCard extends PhoneCard{ long cardNumber; int password; String connectNumber; boolean connected; boolean performConnection(long cn,int pw){ … } }
  • 31. 方法重载例class D200_Card extends Number_PhoneCard{ double additoryFee; D200_Card(long cn,int pw,double b, String c){…} boolean performDial(){ if(!connected) return false; if(balance>(0.5+additoryFee)){ balance-=(0.5+additoryFee); return true; } else return false;} boolean performDial(long cn, int pass){ if(performConnection(cn,pass)) return performDial(); else return false; } double getBalance(){ if(connected) return balance; else return -1;} }
  • 32. 方法重载例class D200_Card extends Number_PhoneCard{ double additoryFee; D200_Card(long cn,int pw,double b, String c){…} boolean performDial(){ if(!connected) return false; if(balance>(0.5+additoryFee)){ balance-=(0.5+additoryFee); return true; } else return false;} boolean performDial(long cn, int pass){ if(performConnection(cn,pass)) return performDial(); else return false; } double getBalance(){ if(connected) return balance; else return -1;} } 方法实现
  • 33. 方法重载例class D200_Card extends Number_PhoneCard{ double additoryFee; D200_Card(long cn,int pw,double b, String c){…} boolean performDial(){ if(!connected) return false; if(balance>(0.5+additoryFee)){ balance-=(0.5+additoryFee); return true; } else return false;} boolean performDial(long cn, int pass){ if(performConnection(cn,pass)) return performDial(); else return false; } double getBalance(){ if(connected) return balance; else return -1;} } 方法覆盖方法实现
  • 34. 方法重载例class D200_Card extends Number_PhoneCard{ double additoryFee; D200_Card(long cn,int pw,double b, String c){…} boolean performDial(){ if(!connected) return false; if(balance>(0.5+additoryFee)){ balance-=(0.5+additoryFee); return true; } else return false;} boolean performDial(long cn, int pass){ if(performConnection(cn,pass)) return performDial(); else return false; } double getBalance(){ if(connected) return balance; else return -1;} } 方法实现方法重载方法覆盖
  • 35. 方法重载例public class TestOveride{ public static void main(String[] args) { D200_Card my200 = new D200_Card(12345678,1234,50.0,"200"); if(my200.performDial(12345678, 1234)) System.out.println(“…"+my200.getBalance()); if(my200.performDial()) System.out.println(“…"+my200.balance); } }
  • 36. 构造方法重载构造方法:与类同名的方法,没有返回类型,通过new运算符调用。 作用:实例化对象-初始化对象 类名 对象引用名 = new 构造方法(); 例:Employee emp = new Employee(…); new运算符的参数就是调用类的构造方法,初始化新建的对象,并为对象分配内存空间,返回对该对象的一个引用。 当在类的定义中,没有定义任何构造方法时,系统会为该类配一个隐含的构造方法(如:Employee()),方法中没有内容。 一旦定义了一个构造方法,隐含构造方法失效!
  • 37. 构造方法重载构造方法重载定义: 同一个类中存在若干具有不同参数列表的构造方法,完成不同的初始化功能。 例: D200Card(){} D200Card(long cn){ cardNumber = cn;} D200Card(long cn, int pw){ cardNumber = cn; password = pw;} D200Card(long cn, int pw, double b, String c){ cardNumber = cn; password = pw; balance = b; connectNumber = c; }
  • 38. 构造方法重载例class Employee { String name; int age; float salary ; Employee() { } //没有参数的构造方法 Employee(String n) { //有一个参数的构造方法 name = n ; //为职工姓名赋值 } Employee(String n , int a ){ //两个参数的构造方法 name = n ; //为职工名字赋值 age = a ; //为职工年龄赋值 }
  • 39. 构造方法重载例 Employee(String n,int a,float s){ //三个参数的构造方法 name = n ; age = a ; salary = s; } void print() { //打印职工对象信息的方法 System.out.println("职工" + name + " 年龄:" + age + " 工资:" + salary ); } }
  • 40. 构造方法重载例public class Test { public static void main(String[] args){ Employee emp0 = new Employee() ; emp0.print() ; Employee emp1 = new Employee("赵红") ; emp1.print (); Employee emp2 = new Employee("李力",20) ; emp2.print (); Employee emp3 = new Employee("王强",30,3000F) ; emp3.print (); } }
  • 41. 系统类构造方法的重载例Integer类构造方法的重载 方法1:Integer(int value) 例:new Integer(38) 方法2:Integer(String s) 例: new Integer("38") Float类构造方法的重载 方法1:Float(Float value) 例:new Float(3.14) 方法2:Float(String s) 例:new Float("3.14") String类构造方法的重载 方法1: String() 例: new String() //空串 方法2: String(char[] value) 例:char data[] = {'a', 'b', 'c'}; String str = new String(data); //字符串abc 方法3:String(char[] value, int offset, int count) 例:char data[] = {'a', 'b', 'c','d','e'}; String str = new String(data,1,3); //字符串bcd
  • 42. 子类调用父类的构造方法子类继承父类所有的域和方法(非private),但不继承构造方法,子类应该定义自己的构造方法,并调用父类构造方法。 为了保证安全性,在子类的所有构造方法中,必须首先调用一个父类的构造方法。 子类可在自己的构造方法中使用super(参数列表) 来调用父类带参数的构造方法。super(参数列表)调用语句必须是子类构造方法中的第一个可执行语句。 若子类的构造方法中没有super(参数列表)语句,系统将隐含调用父类无参数构造方法。
  • 43. 子类调用父类的构造方法Emplyee类定义: class Employee { String name ; int age ; float salary ; Employee(String n,int a,float s){ name = n ; age = a ; salary = s; } ...... }
  • 44. 子类调用父类的构造方法Manager类的构造方法例: class Manager extends Employee { float allowance ; //再定义一个属性(津贴) Manager(String n,int a,float s , float aa){ //构造方法 super(n,a,s) ; //首先调用父类构造方法 allowance = aa; } ... ...} Director类的构造方法例: class Director extends Manager { ... ... Director(String n,int a,float s,float aa,String tel,String dep){ super(n,a,s,aa) ; //调用父类(Manager)构造方法 telephone = tel ; department = dep; } ... ...}
  • 45. 子类隐含调用父类的构造方法Manager类的构造方法改编如下: class Manager extends Employee { float allowance ; Manager(String n,int a,float s , float aa){ name = n ; age = a ; salary = s; allowance = aa ; } …….} Manager构造方法要隐含调用父类无参的构造方法Employee(), 但Employee类没有这个构造方法,所以编译出错。
  • 46. 子类隐含调用父类的构造方法如果Employee类定义两个构造方法 class Employee { String name ; int age ; float salary ; Employee() { } ; //无参数构造方法 Employee(String n,int a,float s){ name = n ; age = a ; salary = s; } ... 因为Employee类定义了一个无参数的构造函数,前面Manager类的构造方法出现的问题就解决了。
  • 47. 对象初始化三步曲当为对象分配内存空间后,首先将数据域置为: 0 (数值型,字符型) false (逻辑型) null (引用型) 这样,在对象建立后,就有明确的状态,数据域都有值。 执行显式初始化(即类定义中,对数据域进行的初始化) 例 : class Employee { String name = "aaa" ; int age = 20 ; float salary = 1000F ; } 执行构造方法
  • 48. 对象引用的多态一个对象只有一种形式(构造函数确定的),一个对象引用是多态的,因为子类的对象可以作为父类的对象来使用。 Employee e1 = new Employee(…) ; Employee e2 = new Manager(…) ; //将管理员看作是职工 Employee e3 = new Director(…) ; //将领导看作是职工 但下面的语句是错误的: Director d1 = new Employee(…) ; //错:职工不是领导 Director d2 = new Manager(…) ; //错:管理员不是领导 Director d3 = new Director(…) ;
  • 49. 对象引用的多态class Employee { //Employee类定义 String name ; int age ; float salary ; Employee(String n,int a,float s){ //构造方法 name = n ; age = a ; salary = s; } void upSalary(float inc) { //方法-提薪 salary = salary + inc ; } String getInfo() { //方法-取信息 return “姓名:”+name+“ 年龄:”+age+“ 工资:”+salary ; } }
  • 50. class Manager extends Employee { float allowance ; //再定义一个属性(津贴) Manager(String n,int a,float s , float aa){ //构造方法 super(n,a,s) ; //调用父类构造方法 allowance = aa ; //为allowance属性赋值 } void setAllowance(float aa) { //方法-定津贴数 allowance = aa ; } String getInfo() { //方法-取信息 return “管理者:” + super.getInfo() + “ 津贴:” + allowance ; } }对象引用的多态
  • 51. class Director extends Manager { String telephone ; //定义领导特有的属性(电话) String department ; //定义领导特有的属性(部门) Director(String n,int a,float s,float aa,String tel,String dep) { super(n,a,s,aa) ; //调用父类(Manager)构造方法 telephone = tel ; //为属性赋值 department = dep; //为属性赋值 } void setTel(String tel) { //方法-设置电话号码 telephone = tel ; } String getInfo() { //方法-取信息 return name + " 是 " + department + " 部门的领导" ; } }对象引用的多态
  • 52. 多态应用-方法放的通配参数public class Test { public static void main(String[] args){ Employee emp1 = new Employee("赵兵",28,1500.0F); Manager mgr1 = new Manager("徐军",35,1800.0F, 500.0F); Director dir1 = new Director("黄帅",45,3000.0F,500.0F, "2430","计划司"); CalTax ct1 = new CalTax() ; ct1.findTax(emp1); ct1.findTax(mgr1); ct1.findTax(dir1); } } class CalTax { void findTax(Employee e){ System.out.println(e.salary*0.1F) ; } }利用参数的多态性,该方法可接收通配对象。
  • 53. 多态应用—数组的通配同质收集(collection)——一个数组可存储几种类型的对象 public class Test { public static void main(String[] args){ Employee[] staff = new Employee[3] ; staff[0] = new Employee("赵兵",28,1500.0F); staff[1] = new Manager("徐军",35,1800.0F, 500.0F); staff[2] = new Director("黄帅",45,3000.0F,500.0F, "2430","计划司"); for (int i=0;i
  • 54. 多态应用-数组的通配执行结果: 子类继承父类的域和方法,或子类覆盖父类的方法,其域名和方法名是一样的。在对象引用多态时,实际对象决定访问的域和调用的方法。 任何对父类合法的操作,通过父类对象引用对子类对象进行操作也是合法的。反之,对父类不合法的操作,即使子类合法,也不能通过父类对象引用对子类对象进行操作。
  • 55. 多态中的问题如果在上述main()方法中加入下述测试程序段: staff[1].allowance = 600 ; staff[1].setAllowance(600); 编译出错。编译时系统从语法上看(而不是考虑实际的对象,对象是在运行时才确定),employee类没有allowance属性,也没有setAllowance(float)方法。
  • 56. 实例类型的判断与转换问题代码改写如下: if( staff[1] instanceof Manager) { // ① Manager m1 = (Manager)staff[1] ; // ② m1.setAllowance(600.0F) ; // ③ } 代码说明: ① instanceof运算符:判断一个实际的对象是否为某个类的实例; ② 如果是,可通过类型转换将对象转换为实际的类型; ③ 转换为Manager类型的对象后,Manager类的属性和方法就可以使用了。
  • 57. 包(package)包是一种松散的类的集合,通常把需要在一起工作的类放在一个包里,在缺省情况下可以互相访问,类似于操作系统中的用来组织文件的目录。 一般不要求处于同一个包中的类有明确的相互关系,如包含、继承等等。 利用包来管理类,便于类的组织、管理和引用(共享),可实现类的访问权限控制。 系统类库就是以若干个包的形式提供,如:import java.io.* -程序要引用系统io包中的类。
  • 58. 包与类的名字空间所有类成员的名字都是相互隔离的。类A中的方法m1与类B中的方法m1互不相干,但类名就有冲突的问题; 在一个Java程序运行过程中,某些类会从internet上自动下载,而用户并不知晓。所以在java中需要使用名字空间来避免类名冲突问题,以便可以建立一个唯一的类名(类似于文件管理)。 包用于类的名字空间管理。作为包的设计人员,利用包来划分名字空间以避免类名冲突。
  • 59. 包与目录一个包要放在指定目录下,包名本身又对应一个目录(用一个目录表示)。 一个包可以包含若干个类文件,还可包含若干包。 包名可以有层次,以小数点分割,包名一般全小写。 环境变量classpath 指定搜寻包的路径。 JDK安装时配置classpath变量,变量值为 .; d:\Program Files\Java\jdk1.8.0_20\lib; d:\Program Files\Java\jdk1.8.0_20\lib\tools.jar
  • 60. 类的名字空间-包-目录包 p1类c1类c2类c3包 p11包 p2类c2类c3类c4类c1类c5 p2 p11d:\temp类classpath =d:\temp p1包
  • 61. 编译单元的基本概念一个java源代码文件称之为一个编译单元。 一个编译单元中至多只能有一个public类,该类名与文件名相同(可认为是主类),编译单元中的其他类是该public类的支撑类。 经过编译,编译单元中的每个类都产生一个 .class文件。 java的工作程序是一串.class文件,JAVA解释器负责寻找、加载和解释这些文件。 (不象其它语言最终生成一个.exe的可执行文件)
  • 62. 编译单元public class c1{ ... main()...} class c2{...} class c3{...} .java文件class c4{...} class c5{...}c1.class文件c3.class文件c2.class文件c5.class文件c4.class文件javacjavacjava.java文件
  • 63. 编译单元与包 对象创建三步曲: 打开包(import package) 加载类(程序中只有类定义的一份拷贝) 创建对象(用new运算符可以创建一个类的若干实例)编译 单元当前包其他包其他包packageimport
  • 64. package语句常见语句格式: package 包名 ; package 包名.子包名 ; 在一个编译单元中,只能有一个package语句,且为第一个语句。 语句功能-指定当前包 凡在本编译单元中定义的类都属于这个包(对类分组); 本编译单元也可引用当前包中已有的类; 如果编译单元中无package语句,则隐含的当前包是一个无名包(放在当前目录下)。 无名包中的类是为了局部应用。
  • 65. import语句常用语句格式: import 包名.类名 ; //引入指定的类 import 包名.* ; //引入包中的所有类 import 包名.子包名.* ; 例:import java.awt.* ; 该语句引入整个awt 类库(标准Java库的一部分) 例:import java.awt.Label ; 该语句只引入Label类,但awt类库中的其他类不可用。 import使用注意事项: import语句必须出现在所有类定义之前; import语句将所指定包中的类引入当前的名字空间,即告诉编译到哪去找程序中使用的类。
  • 66. 包的使用例包的使用例说明 在d:\emp目录下建立一个名为employee的包; 将Employee、Manager、Director 三个类放入employee包中; 在测试程序中,引用employee包中的类,对上述三个类的对象进行测试。(测试程序放在其他目录下) 包与目录的对应关系 在d:\emp目录下建立包,系统会在该目录下建立employee目录,代表这个包的所在位置; 将Employee等三个类放入employee包中,最终结果是在d:\emp\employee目录下存放3个类文件: Employee.class、Manager.class和Director.class
  • 67. 包的使用例package employee ; // 声明 employee包为当前包 public class Employee{ //生成的类文件放入employee包中 static float c_minSalary=500 ; //静态属性 String name ; char sex ; int age ; float salary ; public Employee(String n,char x, int a, float s) { name = n ; sex = x ; age = a ; salary = s ; } void upSalary(float inc) { salary = salary + inc ; } public String getInfo() { return “姓名:” + name + “ 性别:” + sex + “ 年龄:”+ age ; } }Employee.java
  • 68. 包的使用例package employee ; //声明 employee包为当前包 public class Manager extends Employee { float allowance ; public Manager(String n,char x , int a , float s,float aa ){ super(n,x,a,s) ; allowance = aa ; } public String getInfo() { //改写父类Employee的方法 return "管理者" + super.getInfo() + " 收入:" + (salary+allowance) ; } } //ManagerManager.java
  • 69. 包的使用例package employee ;声明 employee包为当前包 public class Director extends Manager { String telephone ; String department ; public Director(String n,char x, int a, float s, float aa, String t,String d ) { super(n,x,a,s,aa) ; telephone = t ; department = d ; } void setTel(String tel) { telephone = tel ; } String getTel() { return telephone ; } public String getInfo() { return name + “ 是 ” + department + “ 部门的领导” ; } } //DirectorDirector.java
  • 70. 包的使用例javac命令选项: javac -d 目录名 指定存放生成的类文件的位置。 本例由于指定了package语句,所以是将生成的类文件存入指定目录(d:\emp)下的包中(employee包) 如果emp目录下没有employee子目录,系统会自动创建。 如果没有指定 -d 选项,系统就认为employee在当前目录下。
  • 71. 包的使用例import employee.* ; //本程序要用到employee包中的类 public class Test { public static void main(String[] args){ Employee emp = new Employee("赵兵",'男',28,1500.0F); Manager mgr = new Manager("徐军",'女',35,1800.0F,500.0F); Director dir = new Director("黄帅",'男',45,3000.0F,500.0F, "2430","计划司"); System.out.println(emp.getInfo()); System.out.println(mgr.getInfo()); System.out.println(dir.getInfo()); } } Test.java 注意:本文件不要与前面的3个 类文件放在同一包中, 放在一起不需要import.
  • 72. 接口-interface接口-用来组织应用中的各类并调节它们的相互关系的一种结构,用来实现类间的多重继承功能。接口可看着是一种特殊的类。 接口中的方法都是没有方法体的抽象方法 接口中的属性只能是常量 接口定义的仅仅是实现某一特定功能的一组方法的对外接口和规范,而并没有真正地实现这个功能。 接口所规定的一组功能的实现是在继承了这个接口的各个类中完成的,由这些类来具体定义接口中所有抽象方法的方法体。通常把对接口的“继承”称为“实现”。
  • 73. 接口的实现Object类Abstract class classfinal class接口classjava—单重继承继承实现
  • 74. 声明接口 [public] interface 接口名 [extends 父接口名列表] { // 常量域声明 [public] [static] [final] 域类型 域名 = 常量值; // 抽象方法声明 [public] [abstract] 返回值类型 方法名( 参数列表 ) ; } 接口是由常量和抽象方法组成的特殊类。 蓝色修饰符为隐含修饰,可以省略。
  • 75. 实现接口的规定类定义中使用 implements 指定实现某一接口。 如果实现某接口的类不是抽象类,则类中必须具体实现该interface中定义的所有抽象方法,如果不需要某个方法,也要定义成一个空方法体的方法: public 方法名() { } 其中实现的方法必须指定为public限定符。 如果实现某接口的类是抽象类,则其可以不实现该接口的全部方法,但其非抽象子类必须全部实现所有抽象方法。 实现某接口的抽象方法时,必须使用完全相同的方法头,包括返回值,方法名,参数列表(顺序、类型和名称)
  • 76. 接口的应用声明多个类必须实现的方法 编程者可以把用于完成特定功能的方法组织成相对独立的集合体-接口,凡是需实现这种特定功能的类,都必须实现这个接口,如用于消息处理的ActionListener。 利用接口模拟多继承 java程序中的类层次结构是树状结构,这种树状结构在处理某些复杂问题时会显得力不从心。 接口在保持单继承优点的前提下,使Java程序的类层次结构更加合理,更符合实际情况。
  • 77. 例5-16 ImplementActionListener.java import java.applet.*; import java.awt.*; import java.awt.event.*; public class ImplementActionListener extends Applet implements ActionListener{ TextField pw = new TextField("我是密码"); Button btn = new Button("隐藏"); public void init(){ add(pw);add(btn); btn.addActionListener(this); } public void actionPerformed(ActionEvent e){ pw.setEchoChar('*'); pw.selectAll(); } }
  • 78. (本页无文本内容)
  • 79. 接口例interface CalArea { public static final double pi = 3.14 ; public abstract double cal(double r); } class a implements CalArea { public double cal(double r) { return pi * r *r ; } } public class Test { public static void main(String[] args){ a a1 = new a() ; System.out.println(a1.cal(5.0)); System.out.println(a1 instanceof CalArea ); System.out.println(a1.pi); } }instanceof 运算符可判断一个对象是否为实现了某个接口的类对象。
  • 80. 小 结 继承 域的继承和隐藏;方法的继承和覆盖;this和super 多态 方法覆盖;方法重载(构造方法的重载);对象引用的多态 包及其使用 包的定义和创建;包的使用 接口 接口的定义和实现
  • 81. P143:5-3, 5-4, 5-5, 5-6 P143: 5-7,5-8,5-11,5-12 P143: 5-15,5-17,5-18,5-19,5-21作 业