返回列表 发帖

[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
, B$ m4 \7 S& i% a0 L& H  JPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
1 ]. C# [, Z2 {' K6 m8 F/ h本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。" t9 |' N# X: @  s9 q
5 p$ d2 A7 G* y2 \% v3 v! u
问题
7 Q& y% w! Q$ G+ O$ f  W* {) N- @' q( R/ a7 i% f
1.对象的蓝图是什么?1 W8 b# x2 D) ]
  \0 @2 N* b; V% w3 k& [4 C1 ^
答案:____________
$ \0 n. g% s* M$ w+ l$ E
) w7 g3 ]! X) D$ B2 |
0 k7 ~' Q# ]7 t) m6 a8 I/ P7 }' T2.以下代码执行后,数组$a->my_value中储存的值是什么?(三选)

  1. <?php
  2. class my_class
  3. {
  4.     var $my_value = array();
  5.     function my_class ($value)
  6.     {
  7.         $this->my_value[] = $value;
  8.     }
  9.     function set_value ($value)
  10.     {
  11.         $this->$my_value = $value;
  12.     }
  13. }
  14. $a = new my_class ('a');
  15. $a->my_value[] = 'b';
  16. $a->set_value ('c');
  17. $a->my_class('d');
  18. ?>
复制代码
A.c
2 }4 W* F( z3 Q! G- |% [, bB.b! ], ~+ C2 P5 V& H. M# q3 }/ v3 @
C.a
, X6 p) a4 s' ]: G8 TD.d
0 X1 {; B. u9 M/ ~+ nE.e
- Z# T% C  z7 j* y1 @: f! U7 V7 d& [2 j1 b2 y! G" ]' h

9 `( w6 `; t, `! }; f  i' T3.如何让类中的某些方法无法在类的外部被访问?
. {; y5 X2 A+ `; ^% M* ~* D3 O: N. E8 M/ W  C. I
A.把类声明为private9 S  c. t  x& x1 O0 }& M
B.把方法声明为private* v' |2 _2 \5 w! u
C.无法实现8 ?( a  q% S8 w* n# g4 X
D.编写合适的重载方法(overloading method)
. M  K6 q1 F4 `1 N9 ~* l
$ K( N) @3 v& s1 j+ _; G2 y7 W
" K: I- J7 |, `) m4 K2 B2 L4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
7 K/ @9 L& p$ u$ R
1 E, P  N5 _9 \& O( JA.MVC模式
3 M5 p0 K* f& fB.抽象工厂模式(Abstract factory)  K; H/ k% o3 P& a# C
C.单件模式(Singleton). ^) l. d* ?, Q% w9 d$ \
D.代理模式(Proxy)) C" Z5 b( M7 P9 `5 B' F7 U! M
E.状态模式(State)2 x: B' l5 w+ [4 a2 v3 g4 K" C

; j2 }' j7 S, g; S5 L9 {( B# s# e- |; t) ^2 d0 J. {
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?5 h- Q- J# T" }# I) {0 o1 `

; }) a! |5 r! ], eA.1个
; p6 N  Q* Z9 K$ ]B.2个, K7 o7 }* B& w" g0 L
C.取决于系统资源. W0 m- r" _# C% j! r- t
D.3个4 q6 p5 z) p  I$ d) d
E.想要几个有几个
3 ?. |+ L3 E# g: `% W& E; k9 t2 r1 j9 G) A& {

; j5 {9 P- ?" c, H" B2 ]6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?

  1. <?php
  2. class my_class
  3. {
  4.     function my_funct ($my_param)
  5.     {
  6.         user_error ("Please define me", E_ERROR);
  7.     }
  8.     function b()
  9.     {
  10.         return 10;
  11.     }
  12. }
  13. ?>
复制代码
A.多重继承$ Y; e' X3 w" a6 R* j
B.接口  l; N% F, \# u
C.抽象方法
9 ~9 u& v3 e0 g5 iD.Private方法
7 c0 ]" u5 _. Q; V  S1 wE.函数重载(function overloading)7 S- m* }* n4 `1 t4 T5 \

! C- n5 n1 U) Y* s0 I/ ^+ b* e; E
7.假设定义了一个testclass类,它的构造函数的函数名是什么?1 W* e: j* u7 P2 _& A5 D2 r

. @6 b( }1 q3 ^4 r8 h" P4 c8 Y6 o( IA.__construct4 Z" [$ g4 V2 J* H1 X- X$ @1 n
B.initialize
- A( m/ Q. n2 l7 o9 U" RC.testclass
4 s* j1 `; n7 h% z; L7 rD.__testclass
6 r1 n9 s5 ?6 l3 n9 F2 PE.只有PHP5才支持构造函数: t" \( h1 j7 Z$ e
: b: f* w: ^1 P; \% C
* ~6 w0 R( Q0 t; G6 y1 H
8.一个类如何覆盖默认的序列化机制?. H1 N, V( x& q& p. z! o

9 J5 W, c! I) I3 \" y) G( IA.使用__shutdown和__startup方法+ |) C' y- N9 [) @0 u3 e) f
B.调用register_shutdown_function()函数- m& O4 P' \0 F( i4 g) g
C.使用__sleep()和__wakeup()方法- S9 Y; N5 y! v, Z1 `
D.无法覆盖默认序列化机制
, K0 P+ ?, f1 ?3 t) I7 [E.使用ob_start()将类放入输出缓冲中, @9 |0 ]- h. R' l2 Y3 M+ W
& {# x4 A/ e$ D3 f: h* x

+ E/ l; y$ T6 |1 P& @1 f" y9.以下哪些面向对象的概念无法在PHP4中实现?
4 ]# T2 {  X/ ?& A, @- }7 I  x( E, m+ e3 k" U9 r
@抽象类
; d+ d! ]& E% @9 V1 f4 l4 r9 G@Final类
+ A1 c( e# E# V9 e8 Z$ N% f@Public、private、protected(PPP)方法
  ?8 Z1 u' i( \" A( l8 @@接口
# P$ i: V( C3 C6 R9 u: x' a! W1 H+ Y) r$ E& C" {5 C6 ^  p7 F8 Z) q  U
A.抽象类
+ d6 _+ X; n6 Y2 q( J8 _B.PPP方法' s9 T$ R7 s  L7 Y
C.PPP方法和接口% X& X! G5 v% X' \+ \; _/ b
D.以上所有都不可用
) D' |, F$ @' IE.以上所有都可用1 M- l" n& d4 ^3 {! H* g0 @

  ]3 T/ ^" N4 G# I5 S4 @
5 s* T4 n, r" M  z" a6 F+ ^10.如何在类的内部调用mymethod方法?
: j) v0 T8 {+ A0 m; K. l
2 e, Z: ]; a- O. xA.$self=>mymethod();
( e+ m+ S, X$ tB.$this->mymethod();$ @  |3 \% @7 a1 A9 U$ [* X* A
C.$current->mymethod();+ j9 Z2 M& Y) h6 c/ x# k7 m* I8 g: ~
D.$this::mymethod()
0 i2 W1 L; j  N( T3 A" EE.以上都不对
- B1 E$ y5 T% y' X% V8 J5 ~- o1 y' d! d  o' K
; a8 U* h4 ~" u
11.以下脚本输出什么?

  1. <?php
  2. class my_class
  3. {
  4.     var $my_var;
  5.     function _my_class ($value)
  6.     {
  7.         $this->my_var = $value;
  8.     }
  9. }
  10. $a = new my_class (10);
  11. echo $a->my_var;
  12. ?>
复制代码
A.10' t- `, G9 @& f/ o- X1 _
B.Null/ n2 Q* W* g8 X9 W) b4 J
C.Empty
4 o8 U, `$ C- h4 b1 @% c! S2 dD.什么都没有! J7 K# V  }( q# S2 F
E.一个错误% R; l7 d; O  ]  p, V% ]7 S

' g$ r& M6 Q7 G2 L  @
7 K7 A( d0 F( Q' f7 X  q12.以下脚本输出什么?

  1. <?php
  2. class my_class
  3. {
  4.     var $value;
  5. }
  6. $a = new my_class;
  7. $a->my_value = 5;
  8. $b = $a;
  9. $b->my_value = 10;
  10. echo $a->my_value;
  11. ?>
复制代码
A.10
! S. O6 B$ `2 h$ u( t- U7 I( RB.5
$ H. K8 b! e+ J' M) F5 w) D) }$ XC.2# r6 {* Z3 M/ P" l9 ?  D7 X
D.Null6 I: L/ X8 z2 b0 V% ^; A
E.什么都没有
# |6 l( H0 g; o
$ x' X* ~9 n. ^3 M6 t( Y
* [$ S+ C) s- m1 T13.以下脚本输出什么?

  1. <?php
  2. $global_obj = null;
  3. class my_class
  4. {
  5.     var $value;
  6.     function my_class()
  7.     {
  8.         global $global_obj;
  9.         $global_obj = &$this;
  10.     }
  11. }
  12. $a = new my_class;
  13. $a->my_value = 5;
  14. $global_obj->my_value = 10;
  15. echo $a->my_value;
  16. ?>
复制代码
A.5! \* ?' W' v3 f6 n& r6 T9 J
B.10
* N+ W3 ]4 s3 t: r. n/ i/ I: J& pC.什么都没有$ ^4 |4 t0 f; }% U
D.构造函数将报错
9 m6 b4 Y) g' ^5 l: r$ mE.510
5 y/ p+ B, Z, G) }1 k9 v9 U( E3 T6 c; S

! W, d$ n0 f% ]; I) B7 n7 S14.考虑如下一段代码,执行时,$eight_tenths->to_string方法返回的字符串是8/10而不是希望的4/5,为什么?

  1. <?php
  2. class fraction {
  3.     var $numerator;
  4.     var $denominator;
  5.     function fraction($n, $d) {
  6.         $this->set_numerator($n);
  7.         $this->set_denominator($d);
  8.     }
  9.     function set_numerator($num) {
  10.         $this->numerator = (int)$num;
  11.     }
  12.     function set_denominator($num) {
  13.         $this->denominator = (int)$num;
  14.     }
  15.     function to_string() {
  16.         return "{$this->numerator} / {$this->denominator}";
  17.     }
  18. }
  19. function gcd($a, $b) {
  20.     return ($b > 0) ? gcd($b, $a % $b) : $a;
  21. }
  22. function reduce_fraction($fraction) {
  23.     $gcd = gcd($fraction->numerator,
  24.     $fraction->denominator);
  25.     $fraction->numerator /= $gcd;
  26.     $fraction->denominator /= $gcd;
  27. }
  28. $eight_tenths = new fraction(8,10);
  29. /* Reduce the fraction */
  30. reduce_fraction($eight_tenths);
  31. var_dump($eight_tenths->to_string());
  32. ?>
复制代码
A.reduce_fraction函数必须返回一个值8 D8 h$ w* x4 m. e% `2 J
B.reduce_fraction函数必须接受一个整型值/ I# P3 f# t8 m
C.gcd函数有问题7 n) W- Y. X/ K. O0 g8 B6 U# K
D.必须通过引用的方式传递$eight_tenths对象
1 O0 d8 g7 p7 Q3 t6 i# @; rE.对象的实例不能传递给方法以外的其他结构。/ ?4 g- E5 K9 p

2 P7 A" W' w, C: G
8 [. t6 R1 k/ N/ F" y9 g15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法" f, e" y9 e9 V0 g; @/ `4 }  C
B.生成myclass的实例并调用mymethod方法
0 ^& {5 ^  _/ U2 K% DC.产生一个语法错误) j$ h- G, i# [+ `5 F" W  H
D.默认myclass类最后被创建出的实例并调用mymethod()
7 k* N9 w1 w( i0 {E.调用名为myclass::mymethod()的函数- s+ f4 ?6 O  k
& p) I7 z4 B1 E1 u. v* x- G
+ S3 h4 \! I9 F! N. e+ [; x" |: R
16.PHP中有静态类变量吗?+ Z) P- L7 ~. t/ `; L- g

# F5 \$ {9 R  O) _A.有
- s- k" b5 B- m( \% R9 wB.没有
" k" k+ f/ T: f5 w( B9 L+ w
4 r# j0 h( a) k9 ~3 Z" v, X4 _; S/ Z7 j. d. L9 Q1 |
17.以下脚本输出什么?

  1. <?php
  2. class a
  3. {
  4.     function a ($x = 1)
  5.     {
  6.         $this->myvar = $x;
  7.     }
  8. }
  9. class b extends a
  10. {
  11.     var $myvar;
  12.     function b ($x = 2)
  13.     {
  14.         $this->myvar = $x;
  15.         parent::a();
  16.     }
  17. }
  18. $obj = new b;
  19. echo $obj->myvar;
  20. ?>
复制代码
A.1
8 m" s2 ^9 L' J9 aB.2
' Q$ T" r; R; \! _6 k# [" O6 ~C.一个错误,因为没有定义a::$myvar
" L0 Z- f$ i) A5 |D.一个警告,因为没有定义a::$myvar; I+ g* V0 O+ l+ t9 h% G
E.什么都没有
/ D9 |* x1 M3 k2 H- t0 y" @
# L2 l" _/ l4 k# b4 o. i2 J2 T: |: w& T. c4 e
18.如何即时加载一个类?
& H+ b* d' m% _! r4 c  Q. Q+ E- J6 Y( S
A.使用__autoload魔术函数
0 g& h  K; j# x! u" e9 ]" N* WB.把它们定义为forward类+ Y! `7 I: k& X5 ^
C.实现一个特殊的错误处理手段  @+ V) O8 n6 i' l# E$ |
D.不可能4 T* j' O/ D+ t% c
E.用有条件限制的include来包含它们
* v# Q, j- f+ V$ K4 [# r
" a4 Y0 X0 }) s1 L' [% n- \/ F1 ]
) }1 U3 J8 _- g) h  a- W* d  W9 a19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?! I3 W) w0 _' ?% x4 h

( N; {% A; Q) S! g$ {! F# Y    答案:__________$ v, ^0 W* a+ P2 B7 j, a
5 ^1 X: j( l5 D/ p- ]/ w
, Y* F/ `  I7 Z) p8 u/ b) Z
20.以下脚本输出什么?

  1. <?php
  2. class a
  3. {
  4.     function a()
  5.     {
  6.         echo 'Parent called';
  7.     }
  8. }
  9. class b
  10. {
  11.     function b()
  12.     {
  13.     }
  14. }
  15. $c = new b();
  16. ?>
复制代码
A.Parent called
8 b+ R$ U( G' MB.一个错误% h! ~! |& M. e6 s5 i
C.一个警告
8 T4 a1 K/ @* r) P1 @6 G) OD.什么都没有
0 _- [: o7 x0 ]4 O; s* k% x
7 g5 z7 _% h+ B3 m$ D* U# @
) ~9 ?  A7 f3 Q$ T/ V6 \2 |' i1 Z6 w: M8 k2 j6 T3 d  G1 t9 }8 |
答案速查) d9 Q; w% ^% P5 P% P; C. d1 b
1.类' k  Y4 y, k  \% ^
2.BCD
( [2 |: [4 E; r+ `- Z8 k6 l1 ^3.C
, V& D+ R/ N( {2 D5 Q. g# z; X6 U4.C3 R6 t* l7 [! |1 o' h
5.A
, x* r6 Z) P' d% ?5 }( N( I6.C
6 h9 a# ^0 [, E$ ^: b+ b7.C
% A- J* k& z8 E0 {( d. M! Q8.C6 P7 g# ?9 _7 W  l  Z7 s7 s2 y! J
9.D
" a5 a% x/ N: d+ ]9 b) f) r" D10.B2 }+ d& O4 u2 z
11.D! ], y7 J& O0 k5 j
12.B
% ^3 p: ?% b. _5 N* Q' F0 U13.A
8 C% m, ?, ~6 p8 ^4 ~14.D3 r8 |: O% `4 u; @3 c: U9 {
15.A
, X# O( O5 i! F* O5 N5 u$ [+ E( D16.B2 r$ g$ |5 J9 R
17.A
) X9 K( K& g% e$ G3 R: V9 v* F18.D4 Z- P8 [) d/ x! o
19.设计模式$ D  q) R$ e% \) n# D8 @9 y  k
20.D$ S% [3 r9 f. r" G9 f. i
* T: Y: _- a# [$ U* R3 B

$ o/ u% L# c. v1 i6 ~9 H1 D2 c6 v# Y% A# ^
答案详解
. q( P% |9 g: W/ ^( a! M4 b4 ~/ r* d4 }: y9 H, y$ d+ Q
1.类是对象的蓝图(对象是类的实例)。6 e6 [/ g* s- N0 a

" Y% y% C4 q! R2 S5 Y! F2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。
; S6 J  Y; h7 D0 R' L2 T  F0 W8 F* d, l3 ?6 L
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
3 b& `3 e6 G, P
/ r3 r; P# z5 P4 z: I4.单件模式可以限制一个类被实例化的次数。6 \# s1 M3 Y2 V$ |& I
- r6 u2 j/ B) d" d9 U$ q( T
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。* x6 t  x3 H/ k) |. e
& F! g$ ^& t4 {
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
7 O$ D/ @+ n9 U) z8 ^
) D9 ^& }) q' e. z0 [; A7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。8 j1 C3 W$ N2 @& V4 n1 j" J

$ _6 n0 M/ x+ U( i8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。( ~1 }# t( Y% Q0 E1 Y
" V; X$ K8 ^6 o0 d& L
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。- x1 C( n5 m6 E$ g3 J# A! `
* P/ P% s( \9 m
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。+ P0 v/ X, |7 N& {9 t& t

5 q! a% d% l) H% D0 e6 L11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。8 D0 y  ?  n( D  _' U

# Q- P( e2 l$ V6 S1 H$ D: ?1 ?12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
. H) _% T% m8 x$ H) f% n
0 R% k: j  k& \$ J; e: u13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。# I0 a* ]" n- ^/ R
5 f, g* H) b) T! l1 p+ O% E
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
5 ~3 z& s6 d( K$ n回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
" |, @# y" z0 Y) G" a    function reduce_fraction(&$fraction)
% T% O  v/ G' ^" A6 w9 q7 w答案是D。/ w9 q) R) _8 `
& f0 u/ p6 M5 T3 F# G- u
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。  ~6 l' |% Z/ m' B! t1 d4 M
8 ?& ^$ ]+ g0 r4 v: L/ E
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。# p( x* }7 c, C2 D4 |$ O

' t& K" A1 K6 G7 A$ |* \1 G+ Q17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。3 R# |" p! N- V- n1 ^

3 p, ?; l2 e* A' K2 g" A18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
- |/ X; O9 d1 O  Q* I+ M
7 |0 U  n1 s" X/ J4 W9 V+ Q. i- o19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。1 c9 A; P, z: N! [+ S
, W: h& c, J) z& K% ]! A, x$ i+ d
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

返回列表
【捌玖网络】已经运行: