OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Similar documents
OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

OOP with Java 通知 Project 3: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票

OOP with Java 通知 Project 7, 6 月 14 日晚 9 点 本周四上机课正常进行 答疑 本周三, 周五下午 1:00 3:00, 理科楼 B911 6 月 12 日考试 ( 随堂 ) 下午 1:00-3:00 教书院 218

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

软件工程文档编制

슬라이드 1

OOP with Java 通知 : Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢

OOP with Java 通知 : Project 2 提交时间 : 3 月 15 日晚 9 点

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

untitled

Strings

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款

Microsoft Word - 新1-12.doc

2009年3月全国计算机等级考试二级Java语言程序设计笔试试题

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

javaexample-02.pdf

Chapter 9: Objects and Classes

Microsoft Word - 01.DOC

OOP with Java 通知 Project 2 提交时间 : 3 月 21 日晚 9 点 作业提交格式 学习使用 文本编辑器 cmd, PowerShell (Windows), terminal(linux, Mac)


3.1 num = 3 ch = 'C' 2

JavaIO.PDF

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

无类继承.key

CC213

《大话设计模式》第一章

untitled

Java Access 5-1 Server Client Client Server Server Client 5-2 DataInputStream Class java.io.datainptstream (extends) FilterInputStream InputStream Obj

untitled

untitled

Java

chap07.key

Guava学习之Resources

Thinking in Java 3rd Edition

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

FY.DOC

C 1 # include <stdio.h> 2 int main ( void ) { 4 int cases, i; 5 long long a, b; 6 scanf ("%d", & cases ); 7 for (i = 0;i < cases ;i ++) 8 { 9

1 LINUX IDE Emacs gcc gdb Emacs + gcc + gdb IDE Emacs IDE C Emacs Emacs IDE ICE Integrated Computing Environment Emacs Unix Linux Emacs Emacs Emacs Un

EJB-Programming-4-cn.doc

Microsoft Word - ch04三校.doc

第3章.doc

chp6.ppt

untitled

Microsoft Word - chap10.doc

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

提问袁小兵:

全国计算机技术与软件专业技术资格(水平)考试

untitled

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

附录J:Eclipse教程

RxJava

Microsoft Word - 物件導向編程精要.doc

c_cpp

(6) 要 求 付 款 管 理 员 从 预 订 表 中 查 询 距 预 订 的 会 议 时 间 两 周 内 的 预 定, 根 据 客 户 记 录 给 满 足 条 件 的 客 户 发 送 支 付 余 款 要 求 (7) 支 付 余 款 管 理 员 收 到 客 户 余 款 支 付 的 通 知 后, 检

Microsoft PowerPoint - CPP-Ch Print.ppt [兼容模式]

<4D F736F F D20C8EDC9E82DCFC2CEE7CCE22D3039C9CF>

untitled

新版 明解C++入門編

内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指

C/C++语言 - C/C++数据

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

Microsoft PowerPoint - L17_Inheritance_v4.pptx

(procedure-oriented)?? 2

Microsoft Word cppFinalSolution.doc

<4D F736F F F696E74202D20B5DA3035D5C220C3E6CFF2B6D4CFF3B8DFBCB6B3CCD0F2C9E8BCC6>

一、

尽 管 Java 语 言 是 在 C++ 语 言 基 础 上 发 展 起 来 的, 但 是 有 别 于 C++,Java 是 一 种 纯 粹 的 面 向 对 象 语 言 (Object-oriented language) 在 像 Java 这 样 纯 粹 的 面 向 对 象 语 言 中, 所 有

模板

Microsoft PowerPoint - plan08.ppt

尽 管 Java 语 言 是 在 C++ 语 言 基 础 上 发 展 起 来 的, 但 与 C++ 不 同,Java 是 一 种 纯 粹 的 面 向 对 象 语 言 (Object-oriented language) 在 Java 世 界 中, 所 有 事 物 都 是 Object 1. 通 过

相 应 功 能 (5) 再 将 Boy 类 作 为 Girl 类 的 友 元 类, 在 Boy 类 的 某 成 员 函 数 VisitGirl(Girl & ) 中 访 问 Girl 类 的 私 有 成 员, 观 察 编 译 器 给 出 的 信 息 ( 6 ) 删 除 两 个 类 中 的 函 数 V

RunPC2_.doc

, 即 使 是 在 昏 暗 的 灯 光 下, 她 仍 然 可 以 那 么 耀 眼 我 没 有 地 方 去, 你 会 带 着 我 么 杜 晗 像 是 在 嘲 笑 一 般, 嘴 角 的 一 抹 冷 笑 有 着 不 适 合 这 个 年 龄 的 冷 酷 和 无 情, 看 着 江 华 的 眼 神 毫 无 温

ebook55-13

untitled

使用MapReduce读取XML文件

CC213

新・明解C言語入門編『索引』

Chapter 9: Objects and Classes

27 :OPC 45 [4] (Automation Interface Standard), (Costom Interface Standard), OPC 2,,, VB Delphi OPC, OPC C++, OPC OPC OPC, [1] 1 OPC 1.1 OPC OPC(OLE f

C++ 程式設計

华恒家庭网关方案

C 1

運算子多載 Operator Overloading

穨文件1

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

java2d-4.PDF

Transcription:

OOP with Java Yuanbin Wu cs@ecnu

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

复习 Protected 可以被子类 / 同一包中的类访问, 不能被其他类访问 弱化的 private 同时赋予 package access class MyType { public int i; public double d; public char c; protected void set(double x) { d = x; protected void set(int y) {i = y; public double get() { return d; public class MySubType extends MyType{ public void set(double x){ i = (int)x; public void set(char z) {c = z; public static void main(string [ ]args){ MySubType ms = new MySubType(); ms.set(1.0); System.out.println(ms.get()); System.out.println(ms.i); System.out.println(ms.d);

复习 Upcasting 继承 子类具有父类的所有方法和数据 Sub-class is a type of base class 类型转换 : 父类的引用可以指向子类对象 class Instrument { public void play() { static void tune(instrument i) { //... i.play(); public class Wind extends Instrument { public static void main(string[] args) { Wind flute = new Wind(); Instrument.tune(flute);

复习 final 关键字 final 数据 static final int j = 1; final int[ ] a = new int [10]; Blank final, 构造函数中初始化 final 参数 final 方法 : 不能重写 final 类 : 不能继承 immutable

Quiz public class Test{ public static void main(string []args){ Integer i = new Integer(10); Integer j = i; i += 10; System.out.println(i); System.out.println(j);

Quiz class MyType { int i; double d; char c; public void set(double d){ d = d; public double get(){ return d; public static void main(string []args){ MyType m = new MyType(); m.set(11.0) System.out.println(m.get());

Quiz class Base { public void show() { System.out.println("In Base"); class Derived extends Base { public void show() { System.out.println("In Derived"); public class Main { public static void main(string[] args) { Base b = new Derived(); b.show();

Quiz class Base { public Base() { System.out.println("In Base"); class Derived extends Base { public Derived() { System.out.println("In Derived"); public class Main { public static void main(string[] args) { Base b = new Derived();

Quiz class Base { private void show() { System.out.println("In base"); class Derived extends Base { public void Derived() { System.out.println("In Derived"); public class Main { public static void main(string[] args) { Derived d = new Derived(); d.show();

多态 Upcasting 与多态 动态绑定 Downcasting

Upcasting 类型 基本类型 (byte, short, char, int, long, float, double) 类 (class, array) 类型检查 基本类型的转换关系 class A 的引用只能指向 class A 的对象 class A{ class B{ A a = new A(); B b = new B(); // A a = new B(); compile error

Upcasting Upcasting 同一基类的不同子类可以被视为同一类型 ( 基类 ) 放宽类型一致性 class A{ class B{ A a = new A(); B b = new B(); // A a = new B(); compile error class A{ class B extends A{ A a = new A(); B b = new B(); A a = new B(); // upcasting

Upcasting Upcasting 的优点 简化接口

class Instrument { public void play(int note) { System.out.println( Instrument.play() + n); public class Wind extends Instrument { public void play(int note) { System.out.println( Wind.play() + n); public class Stringed extends Instrument { public void play(int note) { System.out.println( Stringed.play() + n); public class Brass extends Instrument { public void play(int note) { System.out.println( Brass.play() + n); public class Music { public static void tune(wind i) { i.play(); public static void tune(stringed i) { i.play(); public static void tune(brass i) { i.play(); public static void main(string []args){ Wind flute = new Wind(); Stringed violin = new Stringed(); Brass frenchhorn = new Brass(); tune(flute); tune(violin); tune(frenchhorn); Without upcasting

class Instrument { public void play(int note) { System.out.println( Instrument.play() + n); public class Wind extends Instrument { public void play(int note) { System.out.println( Wind.play() + n); public class Stringed extends Instrument { public void play(int note) { System.out.println( Stringed.play() + n); public class Brass extends Instrument { public void play(int note) { System.out.println( Brass.play() + n); public class Music { public static void tune(instrument i) { i.play(); public static void main(string []args){ Wind flute = new Wind(); Stringed violin = new Stringed(); Brass frenchhorn = new Brass(); tune(flute); tune(violin); tune(frenchhorn); With upcasting 1. 接口变简洁 2. play() 方法能正确的调用对应的重写 (override) 后的子类方法 多态 (Polymorphism) 参数 Instrument i 可以代表不同的子类, 并能正确调用它们的方法 ( 即, 有多种表现形态 )

多态 class Super { public void f() { System.out.println( In Super ); public class Base1 extends Super { public void f() { System.out.println( In Base1 ); public class Base2 extends Super { public void f() { System.out.println( In Base2 ); public class Tester { public static void main(string []args){ Super s = new Base1(); s.f(); s = new Base2(); s.f();

upcasting 问题 public class Music { public static void tune(instrument i) { i.play(); public static void main(string []args){ Wind flute = new Wind(); Stringed violin = new Stringed(); Brass frenchhorn = new Brass(); tune(flute); tune(violin); tune(frenchhorn); tune() 方法是如何知道调用哪一个子类的 play()? 多态是如何实现的?

动态绑定 C 语言 编译 源代码 hello.c 编译器 可执行程序 hello.exe hello.o 程序输入 可执行程序 程序输出

C 语言 可执行文件 静态绑定 (static binding) : 函数的位置在编译时确定 #include <stdio.h> void hello(){... int main(){ hello(); 编译 函数 hello() 的机器码 hello() 函数 main() 的机器码 hello();... 编译后, main() 函数能够确定的知道 hello() 函数的位置 源代码 hello.c 可执行程序 hello.exe hello.o

class Instrument { public void play(int note) { System.out.println( Instrument.play() 多态 + n); public class Wind extends Instrument { public void play(int note) { System.out.println( Wind.play() + n); public class Stringed extends Instrument { public void play(int note) { System.out.println( Stringed.play() + n); public class Brass extends Instrument { public void play(int note) { System.out.println( Brass.play() + n); public class Music { public static void tune(instrument i) { i.play(); public static void main(string []args){ Wind flute = new Wind(); Stringed violin = new Stringed(); Brass frenchhorn = new Brass(); tune(flute); tune(violin); tune(frenchhorn); 编译 class Instrument 的机器码 play(note)... class Wind 的机器码 play(note)... class Stringed 的机器码 play(note)... class Brass 的机器码 play(note)... class Music 的机器码 tune(instrument i) { i.play() main() { tune(flute) tune(violin) tune(frenchhorn) 随机给定 tune() 函数的参数? 编译器无法确定 play() 函数的位置!? 动态绑定 (dynamic binding) : 函数的位置在运行时才能确定

public class Shape { public void draw() { public void erase() { public class Circle extends Shape { public void draw() {System.out.println( circle draw ); public void erase() { System.out.println( circle erase ); public class Square extends Shape { public void draw() {System.out.println( square draw ); public void erase() { System.out.println( square erase ); public class Triangle extends Shape { public void draw() {System.out.println( triangle draw ); public void erase() { System.out.println( triangle erase ); public class RandomShapeGenerator { public Shape next() { double r = Math.random(); if (r < 0.3) return new Circle(); else if (r >= 0.6) return new Tirangle(); else return new Square(); upcasting Circle draw() erase() Shape draw() erase() Square draw() erase() Triangle draw() erase() public class Shapes { Private RandomShapeGenerator gen = new RandomShapeGenerator(); public static void main(string []args) { Shape[]s = new Shape[9]; for (int i = 0; i < s.length; ++i) s[i] = gen.next(); for (Shape shp:s) s.draw(); Dynamic Binding

动态绑定 静态绑定 函数的调用在编译后便确定 也称为 early binding 优点 : 快速, 易于 debug 缺点 : 接口繁琐 动态绑定 函数的调用在运行时才能确定 也称 late binding 优点 : 接口简洁 缺点 : 函数调用需要额外开销, 给 debug 带来困难

动态绑定 多态 ( 动态绑定 ) 带来的扩展性 class Instrument { public void play(int note) {System.out.println( Instrument.play() + n); public void adjust() {System.out.println( Instrument.adjust ) public class Wind extends Instrument { public void play(int note) {System.out.println( Wind.play() + n); public void adjust() {System.out.println( Wind.adjust ) public class Stringed extends Instrument { public void play(int note) {System.out.println( Stringed.play() + n); public void adjust() {System.out.println( Stringed.adjust ) public class Brass extends Instrument { public void play(int note) {System.out.println( Brass.play() + n); public void adjust() {System.out.println( Brass.adjust ) public class Music { public static void tune(instrument i) { i.play(); public static void main(string []args){ Wind flute = new Wind(); Stringed violin = new Stringed(); Brass frenchhorn = new Brass(); tune(flute); tune(violin); tune(frenchhorn); 无需改变! 1. 增加新的接口, 并不影响原有的只依赖于旧接口的代码 2. 原因 : tune 的实现只与父类的相关

动态绑定 动态绑定 Java 中的所有方法都采用动态绑定, 除了 final static 原因? 数据成员 (field) 不使用动态绑定

动态绑定 public class Super { public int field = 0; public int getfield() {return field; public class Sub extends Super { public int field = 1; public int getfield() {return field; public int getsuperfield() {return super.field; public class FieldAccess { public static void main(string []args){ Super sup = new Sub(); System.out.println(sup.field); System.out.println(sup.getField()); Sub sub = new Sub(); System.out.println(sub.field); System.out.println(sub.getField()); System.out.println(sub.getSuperField());

动态绑定 构造函数 初始化顺序 分配内存空间, 默认初始化 ( 设置为 0) 初始化父类 ( 递归!) 静态成员初始化 ( 首次创建该类对象 ) 数据成员初始化 ( 按照定义顺序 ) 调用构造函数

动态绑定 构造函数初始化顺序 public class Super { int sup_field = 1; public Super(){... public class Sub extends Super { public int sub_field = 1; public Sub(int f) { 1. 初始化父类 2. 初始化子类的数据 sub_field = f;

class Meal { Meal() { print("meal()"); class Bread { Bread() { print("bread()"); class Cheese { Cheese() { print("cheese()"); class Lettuce { Lettuce() { print("lettuce()"); Output: Meal() Lunch() PortableLunch() Bread() Cheese() Lettuce() Sandwich() class Lunch extends Meal { Lunch() { print("lunch()"); class PortableLunch extends Lunch { PortableLunch() { print("portablelunch()"); public class Sandwich extends PortableLunch { private Bread b = new Bread(); private Cheese c = new Cheese(); private Lettuce l = new Lettuce(); public Sandwich() { print("sandwich()"); public static void main(string[] args) { new Sandwich();

动态绑定 构造函数中使用重写函数 BUG! public class Super { public Super() { System.out.println( Before Super draw ); draw(); System.out.println( After Super draw ); public void draw() { System.out.println( draw ); public class Test { public static void main(string []args){ Sub sub = new Sub(5); public class Sub extends Super { public int field = 1; public Sub(int f) { field = f; System.out.println( Sub + field); public void draw() { System.out.println( draw + field); 1. 子类的方法 : 在子类对象创建之后才有意义 2. 构造函数中, 避免使用将被重写的函数

动态绑定 函数重写 相同的函数 : 函数名与参数列表相同 协变的返回值 被重写的函数返回值可以是原函数的子类 class Grain { public String tostring() { return Grain ; class Wheat extends Grain{ public String tostring() { return Wheat ; class Mill { Grain process() { return new Grain(); class WheatMill extend Mill{ Wheat process() { return new Wheat(); public class CovariantReturn { public static void main(string []args){ Mill m = new Mill(); Grain g = m.process(); System.out.println(g); m = new WheatMill(); g = m.process(); System.out.println(g);

动态绑定 总结 静态绑定 : 函数在编译时确定 动态绑定 : 函数在运行时才能确定 除了 final, static 外所有函数都为动态绑定 在构造函数中减少使用可能会被重写的函数

Downcasting Is-a 关系 父类与子类的接口完全相同 Shape draw() erase() Circle draw() erase() Square draw() erase() Triangle draw() erase()

Downcasting Is-like-a 关系 子类添加了新的方法 Upcasting: 父类引用指向子类的对象 安全的 Downcasting 子类引用指向父类的对象 不安全 Useful void f() void g() MoreUseful void f() void g() void u() void v() void w() 但当一个父类引用指向子类时, 可以将该引用强制转换为子类引用

Downcasting public class Downcasting { public static void main(string []args){ Userful x = new Userful(); Userful y = new MoreUseful(); x.f(); y.f() // y.u(); compile error, u() not in Useful ((MoreUseful)x).u; // run time error ((MoreUseful)y).u; // downcasting Useful void f() void g() MoreUseful void f() void g() void u() void v() void w()