a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 122|回复: 1

[其他] JAVA技巧:在JAVA中如何产生正确的行为

[复制链接]
发表于 2012-8-4 12:28:23 | 显示全部楼层 |阅读模式
知道Java里绑定的所有体例都经由过程后期绑定具有多形性往后,就可以响应地编写自己的代码,令其与基本类沟通。此时,所有的衍生类都保证能用不异的代码正常地工作。或者换用另一种体例,我们可以“将一条动静发给一个对象,让对象自行判定要做什么工作。”
: a2 T; w: w: W/ E  在面向对象的轨范设计中,有一个经典的“外形”例子。因为它很轻易用可视化的形式默示出来,所以经常都用它声名问题。但很不幸的是,它可能误导初学者认为OOP只是为图形化编程设计的,这种熟悉当然是错误的。
+ w* x6 m$ I4 g6 {3 S  I9 m4 k  外形例子有一个基本类,名为Shape;此外还有年夜量衍生类型:Circle(圆形),Square(方形),Triangle(三角形)等等。巨匠之所以喜欢这个例子,因为很轻易理解“圆属于外形的一种类型”等概念。下面这幅担任图向我们展示了它们的关系:
& t! S% x. ~, b9 b4 L9 [6 |  上溯造型可用下面这个语句简单地默示出来:
' A/ s' G/ O1 p" S( r. v- s! p' s  Shape s = new Circle();
& o& C* S2 Z8 ?: F) e8 o: q& A  在这里,我们建树了Circle对象,并将结不美观句柄当即赋给一个Shape。这概况看起来似乎属于错误操作(将一种类型分配给另一个),但现实是完全可行的——因为按照担任关系,Circle属于Shape的一种。是以编译器认可上述语句,不会向我们提醒一条犯错动静。2 K3 P! M+ D. S/ B4 p
  当我们挪用其一一个基本类体例时(已在衍生类里笼盖):2 P9 g5 _" k! ]* d
  s.draw();$ o5 Y4 b/ `5 R3 ?2 W( R8 A5 {1 [
  同样地,巨匠也许认为会挪用Shape的draw(),因为这事实下场是一个Shape句柄。那么编译器若何才能知道该做其他任何工作呢?但此时现实挪用的是Circle.draw(),因为后期绑定已经介入若干好多形性)。$ x) g2 T. Z/ Y& Z* I; e
  下面这个例子年夜一个稍微分歧的角度说了然问题:
6 W/ V9 g# c9 C8 o8 P7 [6 e  //: Shapes.java6 }& Z2 y; `$ J9 {$ w+ U3 m
  // Polymorphism in Java+ I( g9 a9 T2 ?9 H9 E
  class Shape {9 J, ]  Y1 r8 m
  void draw() {}, D5 f) b8 o; c8 u
  void erase() {}% Q1 c0 [" K$ e) y5 d
  }0 T% I5 j0 r3 Q7 A; U" h4 P; [
  class Circle extends Shape {5 g6 F0 v# g$ L, H( ]. H
  void draw() {
2 U' @3 {7 E: k2 \7 w' `  System.out.println("Circle.draw()");
! }, h" v8 k# K6 b  }4 _5 \% c9 o# O: ^: K
  void erase() {
& j  u/ Y  [$ e& J; N, s  System.out.println("Circle.erase()");
4 K  }( o% ?4 @; p4 J  }
* R/ Z; \) ]- F  a8 Q  }. I$ o1 h" U+ F5 ?+ b
  class Square extends Shape {
  D) v! b, E. x6 d1 ?2 t  void draw() {
% H6 S( [; F7 Q% q' N4 j  System.out.println("Square.draw()");0 Q% d: i* y9 }+ _
  }: O* V3 e, K! t8 j6 P  b( Q9 B
  void erase() {1 ^) _" g0 j) o6 X" B4 Q9 j$ Y9 w/ r
  System.out.println("Square.erase()");
. k; G$ h% H6 V  }
3 W( ^7 N  @0 G9 L; j3 G  }
5 Z3 w( s* Z( |# h0 u" M" S1 \  class Triangle extends Shape {& O. Q+ w2 N; a- P
  void draw() {5 B4 h4 p. b# r% f8 R" ^7 E
  System.out.println("Triangle.draw()");: k$ _3 Z% p4 \5 Q2 ^
  }
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:28:24 | 显示全部楼层

JAVA技巧:在JAVA中如何产生正确的行为

  void erase() {2 a) |" L, Y# n1 Q/ i; H
  System.out.println("Triangle.erase()");. d3 D  z; b: I  T) z5 q
  }
/ f. _$ L. f2 c  M  }
; q+ a/ L0 r" C- j6 w# y' P  public class Shapes {# l4 s: G8 p4 O! A
  public static Shape randShape() {; z% P; k* \9 Z5 A6 g' H" J
  switch((int)(Math.random() * 3)) {/ V6 Z1 e3 k( Q, |# f
  default: // To quiet the compiler
: L! B% L/ h3 l- v) [4 n& {  P+ j  case 0: return new Circle();9 I5 o- F* Q6 V- h6 E, T
  case 1: return new Square();5 E: _$ d+ x" d, i* p  a  e! \
  case 2: return new Triangle();- v& V! v1 o6 }# R8 s/ l8 N
  }! f. I  L( q- d. @4 E0 X3 p# E
  }
6 i" r: e" L* p  public static void main(String[] args) {( n0 k8 D9 s  U4 f3 {
  Shape[] s = new Shape[9];8 ^0 N% e4 k* v& @, y# K1 l) e
  // Fill up the array with shapes:. L& P8 j+ F/ H' d& P0 e# d( D
  for(int i = 0; i < s.length; i++)
% o) W, @& i( v" p( K  s = randShape();) Y3 E# z7 \" v/ x
  // Make polymorphic method calls:% Y  ?0 K' \6 T. ?4 a7 M4 j
  for(int i = 0; i < s.length; i++)
7 i( c) f3 W! B+ O+ _  s.draw();6 `; h8 V; m5 |- g6 x( O# J
  }
0 E2 g; y+ U3 s& v) k: U) X  } ///:~9 H% W6 a: T' d% G6 L4 H' J7 o
  针对年夜Shape衍生出来的所有工具,Shape成立了一个通用接口——也就是说,所有(几何)外形都可以描画和删除。衍生类笼盖了这些界说,为每种非凡类型的几何外形都供给了并世无双的行为。
1 Z# ^  M: R0 U  在主类Shapes里,包含了一个static体例,名为randShape()。它的浸染是在每次挪用它时为某个随机选择的Shape对象生成一个句柄。请注重上溯造型是在每个return语句里发生的。这个语句取得指向一个Circle,Square或者Triangle的句柄,并将其作为返回类型Shape发给体例。所以无论什么时辰挪用这个体例,就绝对没机缘体味它的具体类型到底是什么,因为必定会获得一个纯挚的Shape句柄。
5 k& E# Y+ e) k) }2 {0 M+ y4 |  main()包含了Shape句柄的一个数组,其中的数据经由过程对randShape()的挪用填入。在这个时辰,我们知道自己拥有Shape,但不知除此之外任何具体的情形(编译器同样不知)。然而,当我们在这个数组里步进,并为每个元素挪用draw()的时辰,与各类型有关的正确行为会魔术般地发生,就象下面这个输出示例展示的那样:
; [; C0 d6 x. W  Circle.draw()
$ {2 r3 z/ a6 l( ^. Z1 P) y4 x# G! y  Triangle.draw()
5 P8 g0 n( ]6 m! k4 z, }8 b9 W7 J) G  Circle.draw()
3 z. P  i/ w" v8 q3 j; e! H  Circle.draw()
( S% Y5 Q  {3 R. a# B3 `+ }  Circle.draw()
- h* }  ^: a) h6 N5 U( C; ?  Square.draw()- k# y2 |4 l) a1 T# ~
  Triangle.draw(): a  S4 D7 O) s$ k( _
  Square.draw()
! S) Y, k$ v( y3 V: k) n. g7 [; E  Square.draw()( N9 t+ O6 _( M) X. D! N  q$ j
  当然,因为几何外形是每次随机选择的,所以每次运行都可能有分歧的结不美观。之所以要凸起外形的随机选择,是为了让巨匠深刻体味这一点:为了在编译的时辰发出正确的挪用,编译器毋需获得任何非凡的情报。对draw()的所有挪用都是经由过程动态绑定进行的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-6-2 04:28 , Processed in 0.376227 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表