a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 121|回复: 1

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

[复制链接]
发表于 2012-8-4 12:28:23 | 显示全部楼层 |阅读模式
知道Java里绑定的所有体例都经由过程后期绑定具有多形性往后,就可以响应地编写自己的代码,令其与基本类沟通。此时,所有的衍生类都保证能用不异的代码正常地工作。或者换用另一种体例,我们可以“将一条动静发给一个对象,让对象自行判定要做什么工作。”
5 e& o/ t7 W( A# {: W& `$ ^8 Y4 Q  在面向对象的轨范设计中,有一个经典的“外形”例子。因为它很轻易用可视化的形式默示出来,所以经常都用它声名问题。但很不幸的是,它可能误导初学者认为OOP只是为图形化编程设计的,这种熟悉当然是错误的。5 U/ L, t; E1 m8 f$ J7 J* ~
  外形例子有一个基本类,名为Shape;此外还有年夜量衍生类型:Circle(圆形),Square(方形),Triangle(三角形)等等。巨匠之所以喜欢这个例子,因为很轻易理解“圆属于外形的一种类型”等概念。下面这幅担任图向我们展示了它们的关系:! c' o1 Q4 `2 _" c+ y5 E8 f
  上溯造型可用下面这个语句简单地默示出来:* t7 ]9 P8 f6 ?7 w* Z  t
  Shape s = new Circle();" d9 l& z$ ^: C2 q) r
  在这里,我们建树了Circle对象,并将结不美观句柄当即赋给一个Shape。这概况看起来似乎属于错误操作(将一种类型分配给另一个),但现实是完全可行的——因为按照担任关系,Circle属于Shape的一种。是以编译器认可上述语句,不会向我们提醒一条犯错动静。! M8 s) h0 o7 H. E* t6 u" A, l
  当我们挪用其一一个基本类体例时(已在衍生类里笼盖):: N# b7 S  G: K" c# j
  s.draw();
$ u( R& w) J0 X  同样地,巨匠也许认为会挪用Shape的draw(),因为这事实下场是一个Shape句柄。那么编译器若何才能知道该做其他任何工作呢?但此时现实挪用的是Circle.draw(),因为后期绑定已经介入若干好多形性)。8 }5 h) }! ]6 p  H8 D0 V
  下面这个例子年夜一个稍微分歧的角度说了然问题:$ m, O7 H. [5 q( @  e/ s  {
  //: Shapes.java$ D& S. B8 _5 }! V$ f
  // Polymorphism in Java- A3 n3 B5 `) U6 _: }
  class Shape {4 j1 R' `9 i' u3 \' c
  void draw() {}
- K) o, M( S0 N* ~2 s  void erase() {}* D1 K$ Z+ ]- I& n! ^
  }
4 e5 |" B3 c, n1 m, i+ t# b  class Circle extends Shape {
, B0 {3 b0 p9 C- q$ j  void draw() {
7 j( z0 ^) L* R6 v# v  System.out.println("Circle.draw()");
; i8 P( k+ V  J0 l6 z! Y: c  z0 I  }
" [$ ~2 V! V! n' X6 D+ {" x* P& B4 t1 {  void erase() {5 J1 P% f- L" C& f" b5 P1 {
  System.out.println("Circle.erase()");
) b* T- Z" Z0 \$ d* K" q" V  }
" b8 n2 |; u" W/ M6 z9 W4 W  }7 ^) t2 M/ m4 l& Q
  class Square extends Shape {
3 Z. E( s! n# i2 \' X  void draw() {
$ n. C! J4 \2 }9 k  System.out.println("Square.draw()");
" v' t$ Q' t' N3 u8 b9 e  }) J" m  {; w2 H$ ?
  void erase() {
$ {4 e: g" N( ?  System.out.println("Square.erase()");
! g  K, ^9 {. [2 x( B  }
5 C: Y" x' b0 i) i/ Z# {  }
$ o- _7 V, A* b0 G- I* I0 J8 M% w  class Triangle extends Shape {
4 U, N. A7 f8 l. \) r! m  M  void draw() {" H; U; `  |" O' B) ?' W
  System.out.println("Triangle.draw()");
& |* l4 H& u7 c  }
回复

使用道具 举报

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

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

  void erase() {& I. H9 `; m3 i  g/ B8 V
  System.out.println("Triangle.erase()");
: Z( C- P( ^; ~) |* l# A  }* J' C5 f9 G! @9 |- }( C
  }
% y2 ~- m- ]% D( e- E  public class Shapes {# S% q' E* d; K
  public static Shape randShape() {
2 D4 J8 C; h. |  switch((int)(Math.random() * 3)) {
& O) m, Y: [) u$ v$ H  default: // To quiet the compiler2 ?- p# b  @! f( p" E4 C" A7 M
  case 0: return new Circle();
9 _, m( K+ R6 v  case 1: return new Square();
1 q# u* I# C! C$ K  case 2: return new Triangle();+ @0 ?( F. w: [4 N6 x! K& D
  }
- l9 U) q3 K) I  }
7 K; z  M. d4 n' \1 l5 ]  public static void main(String[] args) {& a9 Z3 I/ N! |- ]" }5 [
  Shape[] s = new Shape[9];# y9 F: `9 @  r! t
  // Fill up the array with shapes:4 i  c+ f* U0 B. q3 I5 S
  for(int i = 0; i < s.length; i++)
% ?; J! g- o# {3 Z! f2 a, x2 A  s = randShape();
3 b! c# H0 {5 J0 ^5 f3 W5 g  // Make polymorphic method calls:
, k, Q; U2 x6 t0 m9 T- R  for(int i = 0; i < s.length; i++)
6 O" _" a! P# g- f/ S  s.draw();
; g. I* W, z- p! @7 G  u  }* M& z/ X3 I% v+ F  g8 `+ c, }* Y
  } ///:~/ b% x" |; d+ i2 E
  针对年夜Shape衍生出来的所有工具,Shape成立了一个通用接口——也就是说,所有(几何)外形都可以描画和删除。衍生类笼盖了这些界说,为每种非凡类型的几何外形都供给了并世无双的行为。6 {! w0 H* n+ o3 p
  在主类Shapes里,包含了一个static体例,名为randShape()。它的浸染是在每次挪用它时为某个随机选择的Shape对象生成一个句柄。请注重上溯造型是在每个return语句里发生的。这个语句取得指向一个Circle,Square或者Triangle的句柄,并将其作为返回类型Shape发给体例。所以无论什么时辰挪用这个体例,就绝对没机缘体味它的具体类型到底是什么,因为必定会获得一个纯挚的Shape句柄。
; I) m: W, v+ F6 f- z. w  main()包含了Shape句柄的一个数组,其中的数据经由过程对randShape()的挪用填入。在这个时辰,我们知道自己拥有Shape,但不知除此之外任何具体的情形(编译器同样不知)。然而,当我们在这个数组里步进,并为每个元素挪用draw()的时辰,与各类型有关的正确行为会魔术般地发生,就象下面这个输出示例展示的那样:: v6 L" F+ w0 L2 Y
  Circle.draw()
$ O. o, l. r" o0 y! t% I7 y  Triangle.draw()
7 B" V5 |) i) r- Y4 C  Circle.draw()% }2 D  s2 Y& k! Q' g/ N5 O( r" V( ~
  Circle.draw()3 U+ u0 E5 A8 |( W3 U- N9 G
  Circle.draw()
% g9 A4 A6 J+ l2 f; K8 {  Square.draw()
$ |3 U  O+ t& t5 ]  Triangle.draw()$ [, v, ^! n! t! ^! p) [" I
  Square.draw()( d5 P/ D; D+ w: B+ @% o& @
  Square.draw()0 L+ c1 w% q7 v* E  g4 ]
  当然,因为几何外形是每次随机选择的,所以每次运行都可能有分歧的结不美观。之所以要凸起外形的随机选择,是为了让巨匠深刻体味这一点:为了在编译的时辰发出正确的挪用,编译器毋需获得任何非凡的情报。对draw()的所有挪用都是经由过程动态绑定进行的。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-21 19:52 , Processed in 0.656937 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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