返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
, \- y! `5 r+ H1 y$ ~2 WPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
1 A/ X0 l6 M+ y4 m' f  Y0 C本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。" _# V1 v2 i/ x/ F
$ u/ K- i& j8 [5 G
问题
: U3 f, w4 Y' o+ t- H) i# D
+ O& {# E. j  }3 ?; F1.对象的蓝图是什么?% \2 H" s) r  y! N- V4 }/ u

8 b# @) x& }3 F% b, u) k6 ?答案:____________% R- t, m  Z. g6 g- @
3 Q6 h( h. m) ^( @* v$ }
3 T# X) z! C3 W
2.以下代码执行后,数组$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.c2 k# Z3 Q5 A7 T; @( ?: N- ^5 z# }1 c
B.b+ w2 `4 q- g% h- K5 D- L; \* I* W
C.a
* m$ d) M# S* U# `' }, _D.d9 V6 C5 k) O: @. I9 |$ K
E.e3 s, R) V  l- q
# @* B! }5 \7 K. Q' w; g

; Z- U# e7 U4 L! s, t2 c3 H# Q3.如何让类中的某些方法无法在类的外部被访问?
6 ^- \8 ?% w3 v6 f. l" L2 h$ _0 B" p3 e* Z% W" D, M; A) y
A.把类声明为private
, R0 ?/ J: d5 r  B% i' V0 e) sB.把方法声明为private
2 I5 z# r  k3 _. \C.无法实现  s! F) R: k" V. S
D.编写合适的重载方法(overloading method)
7 m0 m2 t$ d2 K- e* G8 M
% v' D1 s4 O/ b9 k2 x
8 w- p9 ~* T' K4.哪种OOP设计模式能让类在整个脚本里只实例化一次?; K( T) J% G/ P1 ^& k4 P

9 `/ o5 d+ p! r4 \A.MVC模式# N8 P! p! ~2 S  D6 K% r
B.抽象工厂模式(Abstract factory)
! K1 \5 D* L/ C9 OC.单件模式(Singleton)2 D: P5 z. s* f& I1 ^# k
D.代理模式(Proxy)( m/ b! \, s3 U: e( {& {- W
E.状态模式(State)
3 U/ A) G) L) X( o: l6 T: H; z( U3 l: s/ f0 H- f
) j3 g. d2 {/ {  u* F
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?  z6 l) ^, B2 D9 A
1 Y. p" D1 y8 ]
A.1个8 {& f* L4 Y  p: U1 v% j
B.2个9 G$ D4 k& Z9 q6 W9 ^% ]
C.取决于系统资源
7 q4 E) ~4 K% G$ c2 mD.3个
7 _4 Q3 t  l% }( Z7 N! s. JE.想要几个有几个
% B* I/ ?4 P. @* z9 T0 s8 m/ B2 Q( V! l, x/ C$ ^

# j$ C5 J- N8 ^# F4 t6.以下脚本近似的表示了一种在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.多重继承
& o1 c" G* \# e& ~: x; E4 M) a3 BB.接口* L. r. B+ s( t! _
C.抽象方法2 U, l: P% U- R
D.Private方法" C  \( ?8 J. O& U* J1 C
E.函数重载(function overloading): e( u& p4 a) w0 t% ?

" e( D/ r# U" l2 d" F/ _/ s. C, p. p0 r# O5 ]9 _
7.假设定义了一个testclass类,它的构造函数的函数名是什么?
) j/ f4 s8 ?) v5 v  {9 v* z5 |$ P$ ?. W& z
A.__construct
7 s& ?! I" }, eB.initialize
/ [2 V7 D8 l9 b) e4 A; UC.testclass
# C0 d# P4 g. zD.__testclass: y8 z5 Y# G7 R) d+ y) h
E.只有PHP5才支持构造函数
& m3 E$ X8 g  G. k3 a9 M
% @8 n2 R/ p) D4 ^2 k$ ~
; k+ a0 Q% {) V8.一个类如何覆盖默认的序列化机制?
1 R8 q  X  X- x
- M& k- Z+ ~% y+ `! ^8 d6 F& HA.使用__shutdown和__startup方法0 R7 g7 w- d7 y8 _$ z0 g
B.调用register_shutdown_function()函数) Z$ ]) n' L3 T7 s5 l) \
C.使用__sleep()和__wakeup()方法! u5 u8 j5 Q! o6 I! j/ g
D.无法覆盖默认序列化机制
' h: k, y$ j* _* w! j" OE.使用ob_start()将类放入输出缓冲中
* [; F; h& y+ z9 R
' j% o2 S) _9 r; F, G! y' H# q7 h0 a1 f% `8 C0 J$ K) {) ~
9.以下哪些面向对象的概念无法在PHP4中实现?+ K$ {; }% L3 o& ~8 r- A/ V7 {

! [, e. h5 W- v@抽象类
- K+ k" z6 w6 @  W@Final类, V/ B6 Z) y) X6 g1 Q4 ]4 [* C
@Public、private、protected(PPP)方法
# J! I8 t: q5 {/ G& d@接口8 j8 R' t! R& b. B% U5 R" I6 @
; |6 ?0 ?1 B+ m- [' |5 E% o% q
A.抽象类
3 F' E2 }2 e1 t% kB.PPP方法9 p$ l7 C1 r: ?6 j. x
C.PPP方法和接口
% i" L; {# Y  fD.以上所有都不可用2 k% Z& L# |1 w- E3 b* w
E.以上所有都可用
! T: |1 M/ V0 l: B9 l2 X
0 M: D1 ~2 T0 f" W- z& h2 J! p' F5 h  u; g7 c+ D' l
10.如何在类的内部调用mymethod方法?
$ B! p% X* W' \& B/ f. R* O5 ~- T, C/ S" a% A0 A8 H
A.$self=>mymethod();0 ?' C( [0 t9 {! S4 H- `# C: k* i
B.$this->mymethod();% X% H4 X: x9 p3 \2 L/ v- k
C.$current->mymethod();- M& S& u, s' u
D.$this::mymethod()
4 s. m2 n- M3 e1 y0 o) H+ O. `E.以上都不对1 u2 k4 u7 G0 X, r% x4 u

# j( Z8 o5 r4 n1 R- d. j! H
9 n  {6 G+ {( E, J8 t11.以下脚本输出什么?

  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
' C/ r+ j0 S: T5 iB.Null
0 [( R+ h1 m2 M2 S! V; }C.Empty4 o; H6 Z- K3 H$ Q* {
D.什么都没有" `+ P$ {4 J( C1 t* S
E.一个错误
; p- x* b9 o* f: o6 U, g% `! O; c) W' N

; |/ Z& y+ g7 M" o5 i0 r12.以下脚本输出什么?

  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/ n/ q, l1 ?9 J
B.5/ Y3 \+ U8 @6 K0 W, c
C.2
( n( ~% [8 T2 G" K( a* L5 mD.Null2 @+ l  }0 X4 h2 a+ g
E.什么都没有
3 R: H: v, n1 p# @" y  N5 X
2 o$ T) x) g7 S( ^' ]+ r8 D4 Q  L3 m* }9 N7 [5 o( a$ t, `" Y% R+ ?
13.以下脚本输出什么?

  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" C0 i4 Q, c0 P" a9 H: V0 n- G, w
B.10
6 }4 t" z9 {8 s- ^- w7 F- ^* E! C. Q( lC.什么都没有
5 G; W3 d" c! b2 B* }& TD.构造函数将报错
4 Y, g" x% H; @6 G5 F' d: n0 }E.510
% o1 D* ?0 [$ H' e/ \, o1 e4 N# V+ G( C4 U8 p/ Q8 B# J
6 g$ o* |+ k5 U: W' N! ]- U1 w3 w
14.考虑如下一段代码,执行时,$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函数必须返回一个值5 ^$ @4 o  D5 ~
B.reduce_fraction函数必须接受一个整型值
" s8 f( c- i  M% [1 zC.gcd函数有问题
, D* a; m8 z% iD.必须通过引用的方式传递$eight_tenths对象% ~- g: h+ u' |0 R6 W1 ]
E.对象的实例不能传递给方法以外的其他结构。
* t5 Q/ d+ _- ~* N, Z* ?
: l9 K2 N. O, n4 w
& C% P3 @( z% B& g0 r5 z15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法+ w+ _( {' \9 o5 l$ y- E( k
B.生成myclass的实例并调用mymethod方法7 [, F1 d. T& ]+ A3 T8 _
C.产生一个语法错误/ l6 d3 A2 j; @/ \
D.默认myclass类最后被创建出的实例并调用mymethod(), Q7 I: Q* P) k! q& d
E.调用名为myclass::mymethod()的函数* d- k, |/ Z" a

# M% c% s/ j" ]6 Y& S, b# B9 r. p& n- `
16.PHP中有静态类变量吗?
" I* [$ v3 P. z0 o/ R7 Y! M. W2 I
0 N+ u% t2 M* ~$ [2 rA.有
! M$ b8 J. I  hB.没有  B  s6 ~, |) x
8 {" q$ b9 f5 A7 Q
6 K" k0 t2 Y- S5 V% h. n- c
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
1 S( e2 s% a& d2 _6 VB.2" h& \* c8 w4 ~! p
C.一个错误,因为没有定义a::$myvar
/ R3 v/ F' Z/ ~+ jD.一个警告,因为没有定义a::$myvar) o- J6 C' u! w' R! q- w3 U' @) P: j9 c# R
E.什么都没有2 k' I$ Q, y  k$ W: O, S# d
9 M) ]/ \) B- l1 i  @/ S

' D" v, d2 j) p4 C. D/ W) H18.如何即时加载一个类?% Q, H1 p- B. i8 r

! N) z( c6 u: y4 p  KA.使用__autoload魔术函数
$ a* Z' G* b( E" r2 mB.把它们定义为forward类& a7 u# T  h; f7 X" H3 B, L
C.实现一个特殊的错误处理手段
+ _9 ~. T5 u) X- u" pD.不可能
# T9 L2 g3 e4 c6 n0 \  F& Z8 vE.用有条件限制的include来包含它们) A+ h8 ^9 u* w0 n" y3 a+ Y& z8 \
9 [) }' X# z( o8 G1 t# k
* I# L/ \1 V$ b2 d; f+ ]$ n5 ~0 ^
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
$ Q' j, j( D0 N( _- G
( F, J1 _+ x; w4 S1 \! ~    答案:__________
' M# b5 Y" k* m! k! m  E+ I5 E
- i" ^" B: V6 U+ d; x; j7 k2 o; l& M( b0 C  }. P5 |  K8 {# j
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
) W( |  b7 e0 i, x- D# T8 [B.一个错误
9 X% w6 I! _! ?. a/ S2 lC.一个警告
( X6 L) {: J* C+ ~" i, ~D.什么都没有, h; R6 J) I0 y4 n/ W  O

2 n4 f! [2 y3 m( O
% u/ U$ t8 H! I6 f! m
7 S% H7 {9 g* J3 ?! s2 {; L答案速查
7 O) s! J  z) Q" F/ ?1.类8 |' R8 D+ I# l4 [1 g
2.BCD& A% F; r/ I% @. X
3.C" w5 C. Q3 r; I
4.C, C  S$ E/ G8 Y4 W
5.A* s% ~) h+ Q' R
6.C
9 K& h$ }7 O+ B, j  W7.C. x* d# ]' ]0 @( I5 [
8.C
( F0 Q. |1 e$ u. X/ d) d9 N9.D$ u+ B# s6 `* T( |; f
10.B
' m$ q% o7 i' ]/ b) L( r0 g11.D
. |  i* o9 l! C2 y& \7 e12.B
" O0 s3 G  j4 N4 x) t13.A, }" K9 n% s: e- c( B4 Z+ r
14.D- W' B2 d  ~! x- x+ G
15.A) V( U4 D$ @7 H+ }
16.B- G: W" v3 c: d' I
17.A% S/ T6 r/ _* |: d+ A* o
18.D
  P1 M) n2 y9 z19.设计模式
% j5 G' B& ^! M6 L/ W- X4 |% m20.D
) I3 q  t) k* v
& h% R+ F+ F% i$ K; m$ x. @  g# X& X( N+ O. Z/ L5 N/ a
9 r9 m$ {, W$ I" G6 f" P& h
答案详解
/ p: g# p* w8 `9 B3 L$ h  \- X) t& n5 b- w
1.类是对象的蓝图(对象是类的实例)。
4 L% t( v" E( j* D" Y1 S% X0 i& U9 R2 m  A' w
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。$ ~6 @4 Z/ o, H
6 h) Q9 |' V8 ]( E0 V) B  r3 W/ N- p
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
% h( ~+ k& e5 }& R  c. O
* S) Z+ R; `* a$ x1 C* a4.单件模式可以限制一个类被实例化的次数。; D- f9 L6 r2 \+ o  Z* o

4 X* o$ u0 S  ^3 K) |5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。, f8 t2 d1 z4 Q# `
& f5 Z) `7 w7 \% t# v5 K
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
1 L9 r3 K  J1 B4 c1 {6 e/ M2 W* W; P5 L5 H
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
& b9 X4 Q5 E" ?. M) p% p9 v9 Z. q. i; F/ j
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。4 K( f! Q0 G- }: L0 b" Y

% p, J) B* G2 u4 R; u9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
5 s- f# X8 P5 D/ B1 O4 {4 x2 w8 @8 e% D* m5 J$ O  R  C& }
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
2 c8 }) m) ~8 v& Y' ^  B2 _+ P: j( X% S* u7 U8 U, _
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。; w$ d2 \6 Z, q$ n3 n, m
3 d/ C7 G1 e8 a7 k
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
' K7 H. P' E8 E# P9 L
6 j2 e8 R2 T  D1 Q  w, a  i13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。7 B' p! n5 ?( _8 t, j# j9 j

( o* n5 U- E& t$ e5 T14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
/ g4 [& |( n1 b0 b* f回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
6 h" E& p" m/ @0 @( }0 n' u' H    function reduce_fraction(&$fraction)
  x/ o9 M* \7 l4 }: F答案是D。0 K2 M& Z4 |9 M+ R8 Z( ]

0 L$ r/ J2 G, M- c15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
( f8 C* h* [& n" O* |4 X) z
3 b, T- i- ?& H7 _# n; |5 k16.没有。PHP4只允许声明静态函数变量,没有静态类变量。6 T6 w2 F0 X: T  v$ P

! F5 c0 b7 S7 e0 [' o! O9 X17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。/ U5 c0 P5 T1 T5 q  I
  D9 Z8 W2 A' Z1 p6 X
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
3 \" y+ R! k8 c" [. d  _% Y
: Y/ b* q  R0 p- r: m9 L& Q19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
, I3 u+ ]% S+ J1 }5 F% }& J1 Y8 z1 w2 V; e- m* y9 }4 z) F2 F
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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