Java中的面向对象特性.

Slides:



Advertisements
Similar presentations
系統分析與設計 楊子青 H-1 H 、物件導向技術 n 物件導向的基本概念 – 物件、類別 – 封裝、繼承 – 同名異式 ( 多型 ) 、超荷 ( 過載 ) n 物件導向分析與設計及塑模工具 n UML 塑模工具.
Advertisements

单元二:面向对象程序设计 任务二:借书卡程序设计.
第四章 类、对象和接口.
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
JAVA 编 程 技 术 主编 贾振华 2010年1月.
6. 6 Overloading methods and constructors 6
面向对象的程序设计(一).
OUTLINE Android app Devolpment Flow App反組譯解說 實例 簽名詳解 DalvikByteCode
第一章 面向对象程序设计.
程設一.
第二章 JAVA语言基础.
第二部分 Java语言基础篇 第4章 Java语言与面向对象 (之一).
JAVA程序设计 (03) JAVA Programming
第5章 进一步讨论对象和类.
第5章 Java中类、对象、接口 及包的概念 5.1 类的基本概念 5.2 类的继承概念 5.3 抽象类和接口 5.4 包.
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
程設一.
Object-Oriented Java Programming
Ch08 巢狀類別 物件導向程式設計(II).
程式設計實作.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
第5章 面向对象程序设计 本章要点 5.1 面向对象程序设计概述 5.2 Java语言的面向对象程序设计 5.3 方法的使用和对象数组
H、物件導向技術 物件導向的基本概念 物件、類別 封裝、繼承 同名異式(多型) 、超荷(過載) 物件導向分析與設計及塑模工具 UML塑模工具.
物件導向程式設計 (Object-Oriented rogramming)
例外處理(Exception Handling)
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
Java 第28讲:建立删除文件 主讲教师:李焱 讲师.
Classes Lecturer: 曾學文.
CHAPTER 9 建構方法 ROBERT.
第六章 类的扩展与继承.
程式敘述執行順序的轉移 控制與重複、方法 Lecturer:曾學文.
本單元介紹何謂變數,及說明變數的宣告方式。
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
程式設計實作.
创建型设计模式.
Java软件设计基础 5. 继承与多态.
Java程序设计 第9章 继承和多态.
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
Ch01 物件與類別複習 物件導向系統實務.
SPOTO TM JAVA课程 JAVA中的OO语法
中国矿大计算机学院杨东平 第5章 接口和包 中国矿大计算机学院杨东平
Java
3.1 数据类型 3.2 标识符与关键字 3.3 常量 3.4 变量 3.5 运算符与表达式 3.6 一个编程实例
2019/1/16 Java语言程序设计-类与对象 教师:段鹏飞.
2019/1/17 Java语言程序设计-程序流程 教师:段鹏飞.
Java程序设计 第2章 基本数据类型及操作.
第5讲 使用类和对象编程(三) 内部类 实例 程序控制结构 选择语句.
C/C++/Java 哪些值不是头等程序对象
Chapter 5 Recursion.
JAVA 编 程 技 术 主编 贾振华 2010年1月.
《JAVA程序设计》 语音答疑 辅导老师:高旻.
第二章Java基本程序设计.
第7章 异常处理.
第二章 Java基本语法 讲师:复凡.
Inheritance -II.
Interfaces and Packages
第二章 Java语法基础.

Create and Use the Authorization Objects in ABAP
第二章 Java基本语法 讲师:复凡.
方法進階及物件導向基礎 Lecturer: 楊昌樺.
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
Arguments to the main Function and Final Project
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
對於成員(member)存取權的限制 成員的資料被毫無限制的存取,任誰都可以指定任意值給成員,Java語言為了防止這種現象的產生,規定:有一種成員的資料不能任由類別外部的任何人隨意存取。
05 方法. 05 方法 5.1 方法 在一個較大型的程式中,通常會將具有特定功能或經常重複使用的程式,撰寫成獨立的小單元,稱為「方法」(Method),並賦予方法一個名稱,當程式需要時就可以呼叫此方法來執行該段特定程式。(此種重複使用的程式小單元在其他語言中可能稱為程序、副程式或函式, Visual.
第二章 Java基础语法 北京传智播客教育
第6章 继承和多态 伍孝金
Summary
Presentation transcript:

Java中的面向对象特性

本章主要内容 Java程序结构 “开-闭”原则:抽象与封装 类和对象 继承 多态

Java程序结构(一) 包(package)声明:0 or 1 ,in the beginning of the whole file 类的引入(import):0 or more,in the beginning of the all classes, import standard class and existed classes 公开类声明(public classDefinition): 0 or1 ,the file’s name must be same as this class nameclassDefinition: 0 or more ,the number of the classes is not limited interfaceDefinition: 0 or more ,the number of the interfaces is not limited

Java程序结构(二) Example: package project.gui.view; import java.util.Calendar; import java.awt.*; import java awt.event.*; import mywork.form; public class ButtonExample{…} class A{…} interface ButtonInterface{…} …… } class B{…}

简单的Java面向对象程序 Initially each of our Java programs will consist of two classes: a program class and a runner class. Program class: an object of this class defines what our program should do. Runner class: tells the Java interpreter how to run our program.

Program class声明

Runner class声明

Main函数 When you give a class to the Java interpreter it looks for a main method in the class that has the prototype public static void main(String[] args) and begins executing the statements in it.

示例:圆的计算 program constructs a CircleCalculator object called circle program asks circle to read value for its radius program asks circle to calculate its area and circumference program asks circle to display its radius, area and circumference

CircleCalculatorRunner类

构建一个对象 new CircleCalculator() causes these statements to be executed public CircleCalculator() { } Statements

CircleCalculator类

CircleCalculator构造符

readInput方法

doCalculations方法

displayResults方法

对象与消息(一)

对象与消息(二)

构造符声明 Here is a general template for a constructor declaration modifiers ClassName ( formalArgumentList ) { local declarations and other statements }

方法声明 Here is a general template for a method declaration modifiers returnType methodName ( formalArgumentList ) { local declarations and other statements }

编译与运行(一) 这个应用程序需要有三个文件: 每一个java文件都要编译成class文件(bytecode)。 KeyboardReader.java CircleCalculatorRunner.java CircleCalculator.java 每一个java文件都要编译成class文件(bytecode)。

编译与运行(二) 编译完成后,执行 java CircleCalculatorRunner 运行整个程序,结果如下: Enter radius 3 Radius: 3.0 Area: 28.274333882308138 Circumference: 18.84955592153876

课间习题 自己上机实践以上的示例; 能完全读懂程序的流程结构; 根据KeyboardReader.java文件中的readDouble()方法,实现类似的readInt();readLong()等方法; 提高:参考javadoc学习KeyboardReader.java文件中用到的几个IO类和方法。

"开-闭"原则(OCP) “开-闭”原则(Open-Closed Principle)讲的是:一个软件实体应当对扩展开放,对修改关闭[MEYER88],英文原文是: Software entities should be open for extension,but closed for modification.

"开-闭"原则(OCP) 满足"开-闭"原则的设计可以给一个软件系统两个无可比拟的优越性: 1、通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活性; 2、已有的软件模块,特别是最重要的抽象层模块不能在修改,这就使变化中的软件系统有一定的延续性。 具有这两个优点的软件系统是在一个层次上实现了复用的系统,也是一个易于维护的系统。

怎样做到“开-闭”原则?(一)

怎样做到“开-闭”原则?(二) 抽象化是关键! 解决问题的关键在于抽象化。在面向对象的编程语言中,可以给系统定义出一个一劳永逸、不再更改的抽象设计,此设计运行有无穷无尽的行为在实现层被实现。在Java语言中,可以给出一个或多个抽象类或接口,规定出具体类必须提供的方法的特征(signature)作为系统设计的抽象层。这个抽象层预见了所有的可能扩展,因此,在任何扩展情况下都不会改变。这使得系统的抽象层不需修改,从而满足了“开-闭”原则的第二条:对修改关闭。 同时,由于从抽象层导出一个或多个新的具体类可以改变系统的行为,因此系统的设计对扩展是开放的,这就满足了“开-闭”原则的第一条:对扩展开放。

Java的接口(一) 可插入性:如果可以动态的将一个构件移走,并以另一个构件取而代之,这就叫构件的可插入性。 接口(电源插座)、可插入构件(各种电器) 接口是实现构件的可插入性的关键。 Java接口是一些方法特征的集合,这些方法特征当然来自于具体方法,但它们都是一些很重用的方法。接口只有方法的声明,没有方法的实现,因此这些方法在不同的地方被实现时,可以完全具有不同的行为。

Java的接口(二) Java源代码示例: package java.lang; public interface Runnable { public abstract void run(); }

Java的抽象类(一) 抽象类仅提供一个类型的部分实现。抽象类可以有实例变量,以及一个或多个构造符。抽象类可以同时有抽象方法和具体方法。 关键字 abstract 一个抽象类不会有实例,这些构造符不能被客户端调用来创建实例。但抽象类的构造符可以被其他子类调用,从而使一个抽象类的所有子类都可以有一些共同的实现(共性),而不同的子类可以在此基础上有其自己的实现(个性)。

Java的抽象类(二) 抽象类通常代表一个抽象概念,它提供一个继承的出发点。抽象类一定是用来继承的,具体类不是用来继承的。换言之,在一个以继承关系形成的等级结构里面,树叶节点均应当是具体类,而树枝节点均应当是抽象类(或者Java接口)。这样的设计是所有的Java设计师都应当努力做到的! 抽象类应当拥有尽可能多的共同代码;抽象类应当拥有尽可能少的数据。

Java的抽象类(三) Java源代码示例: InputStream接口的源代码 package java.io; public abstract class InputStream { public abstract int read() throws IOException; public int read(byte b[], int off, int len) throws IOException { …… }

怎样做到“开-闭”原则?(三) 对可变性的封装原则:讲的是找到一个系统的可变因素,将之封装起来。这个原则意味着两点: 一种可变性不应当散落在代码的很多角落里,而应当被封装到一个对象里面。同一种可变性的不同表象意味着同一个继承等级机构中的具体子类,因此,读者可以期待在设计模式中看到继承关系; 一种可变性不应当与另一种可变性混合在一起。一般的设计模式的类图的继承机构都不会超过两层,不然就意味着两种不同的可变性混合在一起了。

类和对象 类的组成 Fields Constructors Methods

类声明 类声明 类修饰符(class modifier) [class modifier] class classname [extends superclass name] [implements interfacename{,interfacename} ] {class body} 类修饰符(class modifier) Access Modifier abstract final

Fields/Variables 实例变量 类变量 Instance Variables Final Instance Variables Non-Static Fields Private state of an object(each object has its own copy of instance variables) Final Instance Variables Not modifiable(constant instance variables) Must be initialized 类变量 Static Fields: shared by all objects of the class Final (static) variables must be initialized(constants) Use static class variables to save storage when a single copy of the data will suffice

示例 class Body {//天体类 public long idNum; public String nameFor; public Body orbits; public static long nextID = 0; } —Instance variables: idNum, nameFor, Orbits —Class variable: nextID —Body a,b; a.idNum and b.idNum are independent, but a and b share nextID

Fields修饰符

Static Field Only one copy of such members in the class/ shared by all objects of the class Exist even when no objects of the class exist Also called class variables and class methods Example: nextID

静态初始化块 静态初始化块的存在往往是需要在类载入时完成一些初始化的工作。 class Body { public long idNum; public String nameFor; public Body orbits; public static long nextID; } static { nextID = 20; } Body() { idNum = nextID ++; } … }

Can’t change reference Final Field Class A { int i = 1; public void g(); } Class B { final int j = 9; public static final int k = 20; final int m = (int)(Math.random()*20) final A a1 = new A(); final A a2; … void q(final A x) { x = new A(); x.g(); } public statuc void main(String[] args){ B b = new B(); b.a1.i++; b.a1 = new A(); } …}     No initializer X X is final X Can’t change reference  X

创建对象 Creation by new Memory Allocation Reference General Format: new objecttype (arglists); Body sun = new Body(); Memory Allocation Automatic Reference Declaration(initialization:null) Object reference is valid only if explicitly created Initialization after Creation sun.idNum = Body.nextID++; sun.nameFor = “Sol”;

构造符 构造符和类具有相同的名字; 一个类可以有多个构造符(重载); 构造符可以有0..n个参数; 构造符没有返回值; 构造符总是和new运算符一起被调用。

构造符的示例 class Body { public long idNum; public String name = “<unnamed>”; public Body orbits = null; private static long nextID = 0; Body() { // constructor without argument idNum=nextID++; }// every Body object have a unique idNum } Body sun = new Body(); // idNum=0; sun.name=”Sol”; sun.orbits=null;

构造符重载 Body(String bodyName, Body orbitsAround) { this(); name = bodyName; orbits = orbitsAround; } This(): call another constructor of the class, Body() Creation: Body sun = new Body(“Sol”,null); Body earth = new Body(“Earth”,sun);

初始化的顺序 在一个类里变量初始化顺序由定义顺序决定的,在任何方法(包括构造器)之前得到初始化 首先初始化static对象(如果它们尚未由前一次对象创建过程初始化),然后初始化非static对象 例:创建一个对象的过程: 类型为A的一个对象首次创建或A类的static成员首次访问时,JAVA解释器必须找到A.class A.class的所有初始化模块都会运行( static 初始化仅发生一次) 创建一个new A()时,首先在内存堆中为其分配足够空间;然后清零,将A中所有基本类型设为默认值 显式初始化、执行构造器

初始化的示例 Class Card{ Tag t1 = new Tag(1); Tag(1) Card() { System.out.println(“Card()”); t3 = new Tag(33); } Tag t2 = new Tag(2); void f() {System.out.println(“f()”); } Tag t3 = new Tag(3); } … Card t = new Card(); t.f(); Tag(1) Tag(2) Tag(3) Card() Tag(33) f()

方法的声明 Modifier1 Modifier2…Return-type MethodName(Formal-Parameter List) throw [ Exception-list] { Method Body}

示例 public String toString() { String desc = idNum + “ (” + name + “)”; return desc; } toString is a special method with String as the return type, and without any parameter toString is automatically invoked when an object is used in ‘+’ or ‘+=’ of string operations System.out.println(“Example:”+ sun) Example:0(Sol)

方法的调用 格式: reference. method( actual-parameter-list ) 形参与实参: 传值调用: formal parameters can be changed in methods, but do not affect the actual parameters 传引用:

示例1: public static void halveIt(double arg ) { arg /=2.0; System.out.println(“halved:arg = ” + arg); } …… double one = 1.0; System.out.println(“before:one=” + one); halveIt(one); System.out.println(“after:one=” + one); one=1 arg=0.5 one=1

示例2: name changed public static void commonName(Body bodyRef) { bodyRef.name = “Dog Star”; bodyRef = null; } …… Body sirius = new Body(“Sirius”,null); System.out.println(“before:”+sirius); commonName(sirius); System.out.println(“after:”+sirius); name changed before: 0(Sirius) after: 0(Dog Star)

示例2分析: Body sirius = new Body(“Sirius”,null) main() sirius Refrence IdNum: 0 Name Orbit:null OBJECT Dog Star “Sirius” commonName(sirius) bodyRef.name = “Dog Star” commonName() bodyRef Refrence public static void commonName(Body bodyRef) bodyRef = null

关键字this(一) 当你位于某个函数之内,想取得当前的对象引用(object reference)。这时this关键字因此而生。它仅用于函数之内,能取得“唤起此一函数”的那个对象引用。 Example class Moose { String hairdresser ; Moose(String hairdresser) { this.hairdresser = hairdresser; } field parameter

关键字this(二) Class B { void f( int i ) { ….}} B a = new B(), b = new B(); a.f(1); b.f(2); How does f() work? B.f(a,1); B.f(b,2); Java Compile pass the reference of the current object Within a method, the refrence of current object ——this

方法的重载 Signature: name, number of parameters, types of parameters Overloading: by multiple methods with different signatures Example public Body orbitsAround() { return orbits } public void orbitsAround(Body around) { orbits = around; }

静态方法 静态方法是不对对象施加操作的方法。即它没有隐式参数。我们可以把静态方法看作是没有this参数的方法。 因为静态方法并不操作对象,所以我们不能在一个静态方法中访问实例字段,但可以访问自己类中的静态字段。 最好使用类的名字来调用静态方法。 B.f(a,1); int n = People.getId(); int n = harry.getId();   不推荐

继承 子类/父类 直接父类/间接父类 单继承/多继承 继承层次(tree-like/network-like) Object: 是所有类的父类,它定义了Java系统中每一个类都具有的行为(方法)。

None_Number_PhoneCard 电话卡 PhoneCard 剩余金额 拨打电话 查询余额 继承 继承 None_Number_PhoneCard 有卡号电话卡 无卡号电话卡 卡号、密码、接入号码、接通 对应电话机型号 Number_PhoneCard 获得电话机型号 登录交换机 继承 继承 继承 继承 IP卡 200卡 电话磁卡 电话卡 失效日期 附加费 使用地域 拨打电话 拨打电话 修改密码 拨打电话 拨打电话 IP_Card magCard IC_Card D200Card

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; } }

class magCard extends None_Number_PhoneCard { String usefulArea; boolean performDial() if (balance > 0.9) balance -= 0.9; return true; } else return false;

class IC_Card extends None_Number_PhoneCard { boolean performDial() if (balance > 0.5) balance -= 0.9; return true; } else return false;

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; } }

class IP_Card extends Number_PhoneCard { Date expireDate; boolean performDial() if (balance > 0.3 && expireDate.after(new Date())) balance -= 0.3; return true; } else return false;

class D200_Card extends Number_PhoneCard { double balance; double additoryFee; boolean performDial() { if (balance >(0.5+additoryFee)) { balance -= (0.5 + additoryFee); return true; } else return false; }

Field继承 Field Hiding(字段遮蔽) 注意点: A field with the same name as a superclass’s filed is declared in subclass 注意点: The hidden field in the superclass still exists The hidden field may be accessed by super, or referencing a superclass’s object When a field of an object is accessed, the declared type of the object determine either super- or sub-class’s field will be used

示例 Public class TestHiddenField { public static void main(String args[ ] ) { D200_Card my200 = new D200_Card(); my200.balance = 50.0; System.out.println(“Supper:”+my200.getBalance()); if (my200.performDial()) System.out.println(“Subclass:”+my200.balance); } 0.0 49.5

Method继承(一) 覆写(override) 要求 Replace a superclass’s method implementation by a new one in the subclass 要求 The old method and the new method must have the same signature and return type. (if different, such a redefinition is not overriding, but is simply an example of overloading) The method must be non-static

Method继承(二) 注意点: Super may be used to refer to the overridden method of the superclass Dynamic Method Call: when a method of an object is called, the actual type of the object determine which implementation will be used

class SuperShow { public String str = “SuperStr”; public void show() { System.out.println(“Super.show:” + str); } } class ExtendShow extends SuperShow { public String str = “ExtendStr”; public void show() { System.out.println(“Extend.show” + str); } public static void main(String[] args) { ExtendShow ext = new ExtendShow(); SuperShow sup = ext;

sup.show();//show of actual type, i.e. ExtendShow ext.show(); System.out.println(“sup.str=”+sup.str); System.out.println(“ext.str =”+ext.str); } Two kinds of reference: actual type(ext), super type(sup) Result: Extend.show:ExtendStr // actual type: Extend Extend.show:ExtendStr sup.str = SuperStr // declared type: SuperShow ext.str = ExtendStr // declared type: ExtendShow

抽象方法和抽象类 抽象方法 抽象类 A method has not been specified(signature only) Abstract methods must be implemented in non-abstract subclasses 抽象类 one or more abstract methods Abs. classes may have concrete data and methods

abstract class GraphicObject { int x, y; . . . void moveTo(int newX, int newY) { . . . } abstract void draw(); } class Circle extends GraphicObject { void draw() { . . . } } …

abstract class A { abstract void callme(); void metoo() { System.out.println(“A’s metoo”) } } class B extends A { void callme() { System.out.println(“B’s callme”) } A a=new B(); a.callme(); /*B’s callme*/ a.metoo(); A a=new C(); a.callme(); /*C’s callme*/ a.metoo();

多态(一) 方法(Method) 类型(Types) Overloading(methods with different signatures) Overriding(inheritance with redefinition) 类型(Types) Subclass-object-is-a-superclass-object, so an object can be referenced by the super types A class’s constructor usually invokes a superclass’s constructor, because creating an object also leads to creating another object of the superclass A variable of type Object may refer to any object

多态(二) Casting Up GraphicObject g = new Circle(); g.draw(); Circle.draw() 在C++中 ,用虚函数实现动态绑定; 在JAVA中,缺省情况就是动态绑定;否则可用final定义

多态(三) Polymorphism as implemented with dynamic method binding (also called late binding)is efficient Polymorphism promotes extensibility: new object types can be added without modifying the base system By polymorphism, programs contain less branching (switch) logic in favor of simpler sequential code. This facilitates testing, debugging, and maintenance

实习题 1、编写表示二维点(x, y)的类Point2D,现要求两点间的距离的方法distance。再编写Point2D的子类Point3D表示三维点(x, y, z), 改写 distance方法。并增加求两点内积的方法innerProduct。编写main 方法,来使用Point2D,Point3D及其方法。 2、创建一名为Rational有理数的类执行数学中的分数运算,并编写驱动程序测试此类。 要求用整数变量表示类的private实例变量:

实习题 numerator和denominator。提供一个构造器,使声明类的对象时可以对它们进行初始化。此构造器可按简化形式存储分数,例如分数2/4将1存储在numerator中,2存储在denominator中。提供带缺省值的无参数构造器以防不提供初始值。为下列运算提供public 方法: (1)两个Rational数相加,结果以简化形式存储; (2)两个Rational数相减,结果以简化形式存储; (3)两个Rational数相乘,结果以简化形式存储; (4)两个Rational数相除,结果以简化形式存储; (5)以a/b的形式打印Rational数,其中a为numerator,b为denominator; (6)以浮点格式打印Rational数(可按用户的要求确定小数点后的数)。

实习题 3、 《Java编程思想》第四、六、七章,这三章习题选作3道。 樊闻斌 uliyas@mes.nju.edu.cn 13813901977