面向对象程序设计基础上精选文档.ppt
面向对象程序设计基础上本讲稿第一页,共七十一页抽象n所有编程语言都提供“抽象”功能。n你所能解决问题的复杂程度取决于抽象的种类和质量。n汇编语言对于计算机(机器语言)是一步很小的抽象。n过程化语言(高级语言)对于汇编语言的抽象迈了一大步。但你所考虑的仍然是机器的结构而非问题的结构。n面向对象方法为程序员提供了一种表示问题空间元素的全新的方法,而且不受问题类型的约束。本讲稿第二页,共七十一页对象n“对象”就象是一台小“计算机”:=对象有状态=对象有你要求它执行的操作n现实世界中的对象:=它们都有自己的状态=它们又都有自己的行为n程序中的对象=用属性表示状态=用方法(代码)实现行为本讲稿第三页,共七十一页封装-信息隐藏n“封装”是一种组织软件的方法。其基本思想是把客观世界中联系紧密的元素及相关操作组织在一起,使其相互关系隐藏在内部,而对外仅仅表现为与其他封装体间的接口。从而构造出具有独立含义的软件实现。n封装并不是一个新的概念,但在面向对象的程序设计中提出了一种全新的封装方法类本讲稿第四页,共七十一页封装-信息隐藏n每个类里都封装了相关的数据和操作。在实际的开发过程中,类多用来构建系统内部的模块,n由于封装特性把类内的数据保护得很严密,模块与模块间仅通过严格控制的数据或操作进行交互,使它们之间耦合和交叉大大减少,从而降低了开发过程的复杂性,提高了效率和质量,减少了可能的错误,同时也保证了程序中数据的完整性和安全性。本讲稿第五页,共七十一页在程序中定义你抽象出的类n新类必须在已有类的基础上构造。n在已有类的基础上构造新类的过程称为派生派生。n派生出的新类称为已有类的子类。已有类称为超类(父类)。n子类继承继承父类的方法和属性。n当没有显式指定父类时,父类隐含为java.lang包中的Object类。父类子类本讲稿第六页,共七十一页类定义属性说明 class Employee String name;int age;float salary;Employee e=new Employee();e.name=“张立”;e.age=21;e.salary=528.37F;System.out.println(e.name +”年龄为:”+e.age +“月薪为:”+e.salary );final 类型 常量名=值常量:只能赋一次值本讲稿第七页,共七十一页类定义方法说明n为Employee类增加打印方法将数据和代码封装在一个单一的实体中。class Employee String name;int age;float salary;void print()System.out.println(name +”年龄为:”+age +“月薪为:”+salary );/class 本讲稿第八页,共七十一页对象方法的含义 Employee emp=new Employee();emp.name=“张立”;emp.age=21;emp.salary=528.37F;n一旦对象被建立并被初始化,就可以调用该方法打印这个对象的数据。emp.print();n对象emp执行print 方法操作自己的数据;而不是从外部操作对象的数据。n向对象发消息,让对象做某件事。本讲稿第九页,共七十一页对象的几个特征nEverything is an object=原则上说,你可以将所要解决的问题中的任何一个“概念组件”在程序中表示为一个对象。=对象类似一个变量,可以存储数据,但你还可以让它执行某些操作,处理相应的数据。nEvery object has a type=每个对象都是某个类的实例,都有对应的类定义。nA program is a bunch of objects telling each other what to do by sending messages=所谓对一个对象发信息,就是调用该对象的一个方法。=对象+消息是OOP语言的主要编程模式本讲稿第十页,共七十一页数据的隐藏-封装n属性的访问权限=private=public=默认(相当于package)n使用private 修饰属性后,就不能直接通过对象名访问这些它们,而只能通过该对象的公有方法来间接操作这些属性。n将属性私有化,然后通过公有方法处理它们有很多好处:=方法可以保护数据(做各种合法性检查)。=使得代码可维护性好(方法中的代码可变,但方法的调用形式可以不变)1本讲稿第十一页,共七十一页方法的定义规则n方法名后的小括号是方法的标志。n参数列表是该方法的调用环境传递给它的数据。n返回值是方法在操作完成后返还给调用它的环境的数据。n要指定方法返回值类型。如没有返回值,类型要写 voidn方法名相同,但参数不同,是不同的方法。修饰符 返回类型 方法名(参数列表)throws 异常 本讲稿第十二页,共七十一页方法的参数n方法的参数要有名有型,作用域仅在本方法中,在方法体中可以象方法体自己定义的变量一样使用。n参数是值传递!对象的内容可以改变,但对象的引用决不会改变。n方法的参数可以与类中的属性同名,这时,参数在方法体中将隐藏同名的属性。class Circle int x,y radius;void setCircle(int x,int y,int radius)/*/本讲稿第十三页,共七十一页引用类型值传送基本类型值传送地址传送值传送与地址传送3.143.14AB3.14AB0 x2F0 x2FAB本讲稿第十四页,共七十一页参数传递例class PassTest float m_float;void change1(int pi)pi=100;void change2(String ps)ps=new String(“Right”);void change3(PassTest po)po.m_float=100.0;public static void main(String args)PassTest pt=new PassTest();本讲稿第十五页,共七十一页参数传递例 int i=22;pt.change1(i);System.out.println(“i value is”+i);String s=new String(“Hello”);pr.change2(s);System.out.println(“s value is”+s);pt.m_float=22.0F;pt.change3(pt);System.out.println(“Current pt.m_float is ”+pt.m_float);/main()/class2实参形参copy本讲稿第十六页,共七十一页this关键字class Employee String name;void print()System.out.println(姓名为:+name );class Test public static void main(String args)Employee a=new Employee();a.name=张丽;Employee b=new Employee();b.name=“李峰;a.print();/输出姓名为张丽 b.print();/输出姓名为李峰 /print方法如何分辨要输出的name变量值是李峰还是张丽本讲稿第十七页,共七十一页thisn在调用对象的方法时,编译器做了一些内部处理,print在编译时会变成这样的一种形式:void print(Employee this)System.out.println(姓名为+this.name);同时,对print方法的调用会变成这种形式:a.print()=Employee.print(a);b.print();=Employee.print(b);n可以看到,编译器把一个隐含的参数传给了方法指向被操作对象的引用。n如果你在方法中想拿到这个引用 this 本讲稿第十八页,共七十一页thisnthis this 只能在方法中使用,表示调用该方法的当前对象,或类的当前实例。nthisthis可以省略,但有时必须通过this表示该类的对象的一些属性。n例:class Employee String name,int age,float salary;void setEmployee(String name,int age,float salary)this.name=name;/当参数和属性同名时,必须使用this this.age=age;this.salary=salary;本讲稿第十九页,共七十一页this 例/使用this还可完成一种自调用格式的编码class Employee String name;int age;float salary;Employee setName(String n)name=n;return thisreturn this;Employee setAge(int a)age=a;return this;Employee setSalary(float s)salary=s;return this;class Test public static void main(String args)Employee a=new Employee();a.setName(“赵文).setAge(23).setSalary(2500);本讲稿第二十页,共七十一页Overloding 重载方法名n用同一个名字来表示不同的方法。这些方法同名的原因,是因为它们的最终功能和目的都相同,但由于在完成同一功能时,可能遇到不同的具体情况,所以需要定义含不同的具体内容的方法。n方法名必须相同(是同一类中定义同名方法的情况)。n方法的参数必须不同(同名不同方法是靠不同形式的参数列表来区分,包括形式参数的个数、类型、顺序的不同)。n返回类型可以不同。n利用“重名”现象提高程序的抽象度和简洁性。本讲稿第二十一页,共七十一页系统方法的重载示例nSystem.out.println输出语句中的println方法有多种定义:public void println(int i)public void println(float f)public void println(String s)public void println(Object o)nInteger类:String toString()static String toString(int i)static String toString(int i,int radix)nDouble 类:String toString()static String toString(double d)4重载本讲稿第二十二页,共七十一页方法的重载和可变参数n定义含有多个不同参数的重载方法,可以让方法有多种不同的调用形式。n当方法的参数数目不固定时,可以定义数组参数,但使用上不太方便。nJDK1.5引入了可变参数的语法:返回类型 方法名(参数类型 参数名)=一个方法的可变参数只能有一个=如果有其他参数声明,可变参数必须声明在最后=在方法中使用可变参数时,该参数相当于一个数组,可以按数组的方式使用可变参数=当调用一个方法时,如果同时存在着对应参数数目的重载方法,则该重载方法优先被调用。本讲稿第二十三页,共七十一页可变参数示例class A void print()System.out.println(重载:void);void print(int a)System.out.println(重载:+a);void print(int a,int b)System.out.println(重载:+a+b);void print(int.v)/可变参数v for(int i=0;i=18&a=18&a(0.5+additoryFee)balance-=(0.5+additoryFee);return true;elsereturn false;定义自己的属性隐藏了父类属性balancebalance本讲稿第四十五页,共七十一页属性的覆盖n如何访问被隐藏的父类属性:=调用从父类继承的方法操作的是从父类继承的属性。=使用super.属性名。class D200_Card extends Number_PhoneCard final double additoryFee=0.1;double balance;/覆盖boolean performDial()double getBalance()double getSuperBalance()return super.balance;/访问继承属性 本讲稿第四十六页,共七十一页属性覆盖的示例class test public static void main(String args)a a1=new a();a1.printa();b b1=new b();b1.printb();b1.printa();class a int x=1;void printa()System.out.println(x);class b extends a int x=100;void printb()super.x=super.x+10;System.out.println(super.x+x);111 10011本讲稿第四十七页,共七十一页方法覆盖(overwriting)n在面向对象的程序设计中,子类可以把从父类那里继承来的某个方法改写,形成同父类方法同名、解决的问题也相似、但具体实现和功能却不尽一致的新方法。n定义与父类完全相同的方法,实现对父类方法的覆盖:=完全相同的方法名=完全相同的参数列表=完全相同类型的返回值=抛出的例外要相同=访问权限不能缩小n否则就不是方法的覆盖,而是子类自己定义与父类无关的方法,父类的方法未被覆盖。不正确的覆盖有时会引发编译时候的语法错误。n调用父类被覆盖的方法 super.方法名7-a本讲稿第四十八页,共七十一页抽象方法的实现nPhoneCard类有一个各子类共有的方法:abstract boolean performDial();n这个方法代表的相同功能(拨打电话),但在不同种类的电话卡中,其具体实现是不同的,在PhoneCard的子类中可以具体实现该方法。n子类对父类中抽象方法的实现,实际上也是一种方法覆盖,相当于用一个具体的方法覆盖了父类中抽象的方法。本讲稿第四十九页,共七十一页方法的覆盖PhoneCard类:abstract boolean performDial();double getBalance()Number_PhoneCard类:abstract boolean performDial();double getBalance()final boolean performConnection(long cn,int pw)D200_Card类:boolean performDial()覆盖 实现抽象方法double getBalance()覆盖 实现细节不同6本讲稿第五十页,共七十一页系统类中方法覆盖例njava.lang.Object public boolean equals(Object obj)比较引用型变量(引用同一个对象时为真)class Myclass /该类继承了equals方法 String m_s;Myclass(String s)m_s=s;而类String Date File 都覆盖了equals方法,当对象的类型和内容相同时为真。本讲稿第五十一页,共七十一页系统类中方法覆盖例class test static void main(String args)Myclass mc1=new Myclass(wang);Myclass mc2=new Myclass(wang);if(mc1.equals(mc2)/equals方法继承自Object System.out.println(true);else System.out.println(false);String s1=new String(wang);String s2=new String(wang);if(s1.equals(s2)/String类覆盖了Object的equals方法 System.out.println(true);else System.out.println(false);8本讲稿第五十二页,共七十一页多态-Polymorphismn由于子类继承了父类的属性和方法,所以,子类对象可当成父类对象来使用。n一个类型声明为父类的变量,既可以存储父类对象的引用,也可以存储子类对象的引用,这就是引用类型变量的多态特征。例:/Manager、Director都是Employee的子类 Employee e1=new Manager();/因为经理也是员工 Employee staff=new Employee100;staff0=new Manager();staff1=new Director();/主管是经理,而经理也是员工7-b本讲稿第五十三页,共七十一页方法的参数与多态n方法的参数同样如此,声明为父类类型的形式参数,可以接收子类类型的实参 class Employee /printTaxRate的参数类型为Employee void printTaxRate(Employee e)/.Employee e=new Employee();Manager m=new Manager();/给printTaxRate方法传递了Manager类型的实参 e.printTaxRate(m);本讲稿第五十四页,共七十一页实例类型的判断与转换 public void method(Employee e)if(e instanceof Director)Director d=(Director)e;d.department=“d02”;d.setTel(“9999”);else if(e instanceof Manager)Manager m=(Manager)e;m.setAllowance(7500.0F);else /employee 本讲稿第五十五页,共七十一页实例类型转换规则n按类层次向上转换(cast upward)总是允许的,只需直接赋值即可。Manager m=new Manager();Employee e;e=(Employee)m;e=m;n按类层次向下转换(cast downward),即由父类对象转换为子类对象,编译会首先检查是否可能。n如果编译允许,运行时还要看实际的情况。在没有使用instanceof做检查的时候,对象正好不是要转换的类型,出运行错误。7-c,dOK本讲稿第五十六页,共七十一页castEmployee eManager mDirector dEmployee empDirector director本讲稿第五十七页,共七十一页方法覆盖和多态n如果子类覆盖了父类的方法,多态会使同一形式的对象方法调用产生不同的结果:class F void print()System.out.println(F!);class S extends F void printf()System.out.println(S!);class Test public static void main(String args)F f=new F();f.print();/输出F!f=new S();f.print();/输出S!本讲稿第五十八页,共七十一页方法覆盖和多态n通过父类型的变量调用被子类覆盖的方法,会产生两种不同的调用结果:=如果该变量存储的是父类对象,则调用的是父类的方法=如果该变量存储的是子类对象,则调用的是子类的方法n利用多态的这种特性,子类就可通过覆盖父类中的方法,改变父类中对应方法的执行方式,从而大大增加代码的复用性。本讲稿第五十九页,共七十一页多态中方法覆盖的应用举例n打印对象的属性值是测验Java程序能否正常运行的一项常见任务。当对象的属性数目很多时,输出它们需要多次调用System.out.println方法,非常麻烦。nSystem.out.println方法有一种调用形式:System.out.println(对象名);n我们的设想是:向该方法传递我们要打印的对象,然后该方法就按照我们的要求格式,打印出对象中所有属性的名称和属性的值本讲稿第六十页,共七十一页多态和方法覆盖的应用举例nSystem.out.println(对象名)是系统提供的输出方法,它只会输出如下的结果:输出对象的类型名引用地址n我们没有办法修改它的实现代码,那么如何完成输出任务?本讲稿第六十一页,共七十一页多态和方法覆盖的应用举例n其实,System.out.println(对象名)这个方法的参数类型是java.lang.Object,它调用了另一个重载方法:System.out.println(字符串)具体的调用形式为:System.out.println(对象.toString();n可以看到,该方法是在调用对象的toString方法,而这个方法又是从何而来?本讲稿第六十二页,共七十一页多态和方法覆盖的应用举例n我们知道,任意一个类都是java.lang.Object的子类,这个toString方法就是从它继承而来的,而toString方法可以被子类覆盖。njava.lang.Object中对toString方法的实现是:返回一个如下格式的字符串:对象名引用地址n由此可见,我们看到的输出结果,是由Object类中的toString方法造成的。只要我们覆盖了这个方法,让它返回我们自己规定的由属性和属性值构成的字符串,就可以改变System.out.println(对象名)的输出。本讲稿第六十三页,共七十一页多态与覆盖例子的代码class Employee String name;int age;float salary;Employee(String n,int a,float s)name=n;if(a=18&a=60)age=a;else System.out.println(illegal age);System.exit(1);salary=s;public String toString()return 姓名为:+name+n年龄为:+age+n工资为:+salary+n;本讲稿第六十四页,共七十一页打印Employee中的属性信息/测试类Test对Employee的实例中的属性进行输出class Test public static void main(String args)/构造两个员工对象 Employee e1=new Employee(王刚,22,1000);Employee e2=new Employee(赵艳艳,23,1500);/输出对象e1的属性 System.out.println(e1);/输出对象e2的属性 System.out.println(e2);本讲稿第六十五页,共七十一页多态和方法覆盖的应用举例n多态和方法的覆盖实际上提供了一种编程的模式:我们可以在不改变原有代码的基础上嵌入我们的代码,这大大减轻了的复杂编程时的难度。调用父类对象方法原有系统嵌入子类覆盖方法的代码父类子类本讲稿第六十六页,共七十一页多态和方法覆盖的应用举例nJava自身也利用了多态和方法的覆盖技术,实现许多复杂的编程模型。比如Applet小程序。n由于Applet运行在浏览器中,它和浏览器交互代码很复杂,但这些复杂的代码都在Applet类中完成了。n我们只需要写一个继承java.applet.Applet的子类,然后在子类中覆盖父类的init、start、stop、paint等方法,就可以让Applet在浏览器中执行,操作Applet的显示,这大大降低了编程的难度。本讲稿第六十七页,共七十一页附录NetBeans对方法覆盖的支持本讲稿第六十八页,共七十一页Netbeans编辑器对方法覆盖的支持在子类中,按alt+insert键可调出覆盖方法菜单项,进入选择父类中要覆盖方法的对话框本讲稿第六十九页,共七十一页上机作业3n写一个Ary类实现:=变量:int m_ary;=方法:数组排序:void order()数组输出:void print()求子数组:int subAry(int a1,int a2)n写Main 主类整型数组对ary类的三个方法进行测试。本讲稿第七十页,共七十一页n试验类的继承和多态上机作业4属性:nameagesalary方法:upSalarygetInfoEmployeeManagerDirector属性:allowance方法:setAllowancegetInfo属性:telephonedepartment方法:setTelgetInfon实现类Employee、Manager、Director的属性和方法n在主类中,使用分别Employee、Manager和Director来实例化Employee的对象,并分别调用方法getInfo()来测试多态。本讲稿第七十一页,共七十一页