8, polymorphism

418 views
332 views

Published on

About java polymorphism

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
418
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

8, polymorphism

  1. 1. Polymorphism
  2. 2. Agenda• 概述• 关于耦合• RE - 向上类型转换• 多态• Pitfall: private方法• Pitfall: 属性和静态方法• 扩展• 向下转型• Object getClass()
  3. 3. 概述• 多态, 又称动态绑定(Dynamic binding), 是 OO(面向对象)中继数据抽象(data abstraction) 和 继承(inheritance)之后的第三大特性;• 多态为分离”接口与实现”提供了可能, 这样 能够极大程度的降低程序模块之间的耦合 性.
  4. 4. 关于耦合• 耦合是指如果程序A依赖于程序B的实现, 那么 程序A/B之间存在耦合关系; 耦合会导致程序的 灵活性大幅下降, 考虑这样一个系统: 模块(Module)A依赖于子模块B的实现, 先如今由于某 些 需求需要使用另一种方式实现子模块B, 由于A与B之 间 紧密耦合导致A模块也需要作相应的修改.• 解耦是指通过更加优良的设计来降低程序之间 的耦合性, 在java中可以通过接口(interface)/继 承/多态等特性来达到低耦合的设计;
  5. 5. RE - 向上类型转换 Upcasting• 向上类型转换是指引用可以指向该类及其子类的所有对象, 比如, 按照如下继承关系: Class A A a = new A(); a = new B(); a = new C(); // A的引用可以指向A/B/C B b = new C(); Class B C c = new C(); Class C• 方法在声明时可以指定某个基类或者接口(比如A), 而在调用时则可以 传入相应的具体实现(比如B/C), eg:// 方法声明void f(A a) {......}// 调用A a = new B();f(a);f(new C())
  6. 6. 多态• 方法绑定(method-call binding)是指将方法调用与方 法体联系在一起;• 分为两种类型1), 静态绑定(early binding)指在编译阶段, 指定某个方法调用执行某个方法体;2), 动态绑定(dynamic binding)也称late binding, 是指在运行时根据具体的类型来决定方法调用执行具体哪一个方法的定义. 动态绑定是java采用的一种方法绑定方式, 所谓的多态也就是指方法动态绑定;
  7. 7. 多态• 由于Upcasting特性, 方法(比如:void f(A))在调用时输入的实参(比如: p1) 有可能是不同的具体实现类型: 形参类型本身(class A)及其子类型(class B); 考虑这样一个问题: 如果在方法(f)内调用该实参(p1)的某个方法(比 如: pf), 那么最终调用的是class A还是class B上面的实现? 示例:class A { void pf()...}class B extends A { void pf() ... // override}class C { f(A p1) ... // 形参类型是A}// 使用C c = new C();A a = new B();c.f(a); // 这里会调用class A里面的pf实现还是class B的?
  8. 8. 多态• 根据对方法动态绑定(多态)的解释, 可以确 定在上面的示例中由于运行时具体类型是B, 因此会调用class B中定义的pf方法.• 这就是多态: 运行时根据具体类型的不同, 决定不同的方法调用, 从而体现出不同的行 为;• 示例: demo/Demo1.java
  9. 9. Pitfall: private方法• 在《 7, Reusing Classes 》章节中讲到private方法默认是final, 因 此不能被覆盖;• 示例:public class PrivateOverride { private void f() { print("private f()"); } public static void main(String[] args) { PrivateOverride po = new Derived(); po.f(); // output: private f(); }}class Derived extends PrivateOverride { public void f() { print("public fs()"); }}• 示例: demo/PrivateOverride.java
  10. 10. Pitfall: 属性和静态方法• 对于类属性以及静态方法, 不会有多态行为;• 示例:class A { public int i = 1; public static void f()...}class B extends A { public int i = 2; public static void f()... public static void main(String[] args) { A a = new B(); System.out.println(a.i); a.f(); // }}• 示例: demo/Demo2.java• 示例: demo/Demo3.java
  11. 11. 扩展• 子类可以覆盖父类的方法, 同时也可以通过添加其他的方法进行扩展; 比如:class A { void f()... void g() ...}class B extends A { void m()... // m, n方法是一种扩展 void n()...}• 结合向上转型和多态, 可以通过父类的接口调用子类的方法, 比如:A a= new B();a.f();a.g(); // 运行时与B中的方法进行绑定但是不能调用子类扩展的其他方法,a.m();a.n(); // 编译错误
  12. 12. 向下转型• 向上转型导致具体类型信息的丢失, 进而导 致无法调用子类扩展的其他方法; 这时候就 需要做”向下转型”操作; 参照上一页的示例:((B)a).m();((B)a).n(); // ok• 向下转型不总是一个安全的操作, 如果对象 的类型与目标类型不同那么会抛出 ClassCastException异常;• 示例: demo/Demo4.java
  13. 13. Object getClass()• 在Object基类中定义了Class getClass()方法用 于返回对象的具体类型信息; Class类对应的 是java编译后的.class文件, 该类提供了一些 接口用于获取该类的名称, 属性, 方法等运行 时信息, 参考链接:1), String getName() 返回类名(包含包信息), 比如demo.B;2), Package getPackge() 返回包3), Method[] getMethods() 返回定义的方法......• 示例: demo/Demo4.java

×