返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
. Q$ q* y- ?, N1 sPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。% b( g0 [. h( C% z8 [
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
6 |( n4 y2 E2 R
* V$ }: \+ C! h$ g: T0 h5 i2 {6 k问题
2 Z1 L- D- n( B9 _  Y% s7 u. }
1.对象的蓝图是什么?! F6 g, o+ x* J: E3 P. Y# E8 K
8 z9 \, [4 Y: K. n. X
答案:____________2 p% C9 g9 u1 s+ k8 a9 ]

$ n" X% S: z: c& ^8 y
* ^+ H3 w7 m6 L0 E( u" a2.以下代码执行后,数组$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
. \9 R3 X7 i" j6 K& pB.b- Z0 K' C' c$ x+ v1 E+ c% r8 H
C.a) b7 B+ P" j! f! R1 k( f- s# j
D.d
& g5 C6 F0 z# H7 K/ q. GE.e
! [0 H" C$ m3 z, C7 h# R5 l' c5 F5 V
2 g) a$ _% F5 a
3.如何让类中的某些方法无法在类的外部被访问?0 z) |: ^+ R* o4 I$ @

- _- p" G$ m$ f" q- Y% \A.把类声明为private
6 c2 ~3 i( K8 \+ l6 a* p& WB.把方法声明为private& |/ x4 V2 h# T8 S- C# a$ K4 O. s3 X
C.无法实现/ H& [! q7 w  c: O
D.编写合适的重载方法(overloading method)3 G3 J2 x& H+ R0 J9 x) d: O/ t4 g
4 x, i+ w" ^% o" k6 _

) y1 Z1 N# ]' u; I  _+ V' U4.哪种OOP设计模式能让类在整个脚本里只实例化一次?" }) \" ]$ U# t* H" O( m0 R

; P6 F4 m# z; r! r3 A1 VA.MVC模式
9 {2 B+ J7 v( O$ sB.抽象工厂模式(Abstract factory)8 }7 I6 Q6 A4 ?" k
C.单件模式(Singleton)$ [2 E% A7 V% G; ?, d' m) x* x
D.代理模式(Proxy)
: V/ a5 k6 N  M/ F8 `# h% TE.状态模式(State)
8 ~% j7 C) h/ ^, f% H! F- \' d1 y& e) Z/ f2 ]; \
3 h# C% b+ k3 B3 g* r/ ~" T, Q
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
2 @; c6 n. ?7 i8 d$ b7 Y
2 l. z# ~$ W2 Q0 o+ GA.1个
0 g9 T) O  x" c$ F9 nB.2个/ X% ^. n8 D5 F' M
C.取决于系统资源
4 G5 X/ n# j0 e: ~D.3个
- R( r9 f! O" f, w1 b# fE.想要几个有几个
: S& T5 f$ X7 t# n0 ~7 ?
* i! j3 Z. Y( y. U: l; f, e- U- M" B! ^0 w/ T" P
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.多重继承' t$ h- N4 ~6 O6 w
B.接口7 Z, h6 y+ g) \) p
C.抽象方法$ L% \# x7 o( L5 G
D.Private方法1 H  E' U0 g2 p
E.函数重载(function overloading)) b+ b7 N- F7 R4 L6 K

- v* t$ N! @0 ^) y
2 g' x" p+ |% |( K: P' h7.假设定义了一个testclass类,它的构造函数的函数名是什么?  [1 E7 F: u6 I' Q5 r: B" b9 y* \

) p, z- {# w# GA.__construct
! Y0 K" v/ ~# t6 v# j+ NB.initialize
3 U" f* c. p) G* OC.testclass
: G' j2 z/ ~3 c# G  oD.__testclass7 o% N) D* J' o7 J2 R
E.只有PHP5才支持构造函数! i' g' f% n$ S& o  n# m

+ e  W& m8 ?7 x2 e1 x( ~
1 T5 ~8 v7 ~; C7 J. S7 n8.一个类如何覆盖默认的序列化机制?. ~& y9 J3 v; b

" Z+ W1 A( D2 T; A+ |/ vA.使用__shutdown和__startup方法
' u3 K! X  N4 X% Y( W. ?B.调用register_shutdown_function()函数% x9 [& U; U3 a5 ~7 h
C.使用__sleep()和__wakeup()方法" g5 Z) q3 U/ K
D.无法覆盖默认序列化机制
3 ]- F3 v1 Y5 ]- `* x. t, g  G" @E.使用ob_start()将类放入输出缓冲中9 M  R- o  c1 A) i# l, F0 j6 ~

% f$ K# b  F  H" D, l
1 }$ G$ p& ^6 [6 X- h9.以下哪些面向对象的概念无法在PHP4中实现?- I$ m2 p8 s4 k
* e8 K0 S2 I- H4 H* ]# E, T) [
@抽象类
! s( A9 N. P4 M9 E6 O9 Y- {@Final类0 B  M/ p/ {3 i& {, I# u/ U! Q4 K
@Public、private、protected(PPP)方法
' G7 i; ^0 B4 v; i3 ~3 |- W5 u@接口
" [6 f9 B8 R. ]% {) E- ^, d% Q
2 V( p% G# Q/ R2 t! ], {$ RA.抽象类5 P( R: r3 `0 j$ O. @  n
B.PPP方法
+ q5 `3 k7 i  p" dC.PPP方法和接口
  `' B6 m2 |8 J- x/ ?D.以上所有都不可用
& ~. d4 W# M6 V$ h% o- a! I5 C! uE.以上所有都可用7 M- s4 h$ }( K7 O% W8 r+ H) X
* v, v6 a) y6 K; i; X, Q

- ?1 `+ I8 O/ R6 b9 Q10.如何在类的内部调用mymethod方法?
5 S4 ?9 h  U# Y: ~+ L% C( v0 p& s2 h# l+ h3 q, a3 _+ f
A.$self=>mymethod();1 y  X* K5 N# r' p6 a( K
B.$this->mymethod();
! b% u: z" [+ ~C.$current->mymethod();. E0 Q0 x8 U6 l
D.$this::mymethod()
) H) i* X/ T5 P2 n" X7 a" ^E.以上都不对2 s$ a' B) a/ @; g- R: m& A
( U# h: z1 {1 ?+ E( H9 g3 f/ |

3 Q$ m* r. X3 H11.以下脚本输出什么?

  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  |& P0 k# f( |& ~! p/ |0 J& F2 p
B.Null/ \0 y5 M; k, @) ]! ?6 m
C.Empty
5 Q' K. o# C$ O# S3 @D.什么都没有
. W/ ^) M* P$ }3 U+ G7 e. @E.一个错误
, l# J# C6 ]# k# q7 N0 n* F/ I* H4 N! d
! Q" v+ F, l2 z# Z" q" p, x2 n# X
12.以下脚本输出什么?

  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/ e& b" O1 t! B( Z5 |/ M2 b- `& ^# K
B.5
  ~$ O/ R; Z* H  C+ yC.2
- w, k4 i3 O+ w  ID.Null
& m8 l% P. j( L" e3 j0 OE.什么都没有
# t9 m; L- @# l7 u4 _2 E1 m4 U5 {" H% H, X# p& ?+ R) [# g( i
0 A2 Y: s5 A& x1 [
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.59 v5 f0 y$ [5 h
B.10, S$ w& {3 z! Z6 l) A# T
C.什么都没有4 @) i% K7 u9 Y: V% O
D.构造函数将报错
# R6 m+ t5 a1 \$ NE.510* J' Y5 i- i) O; T

: m6 H% `5 R0 b8 `5 {9 F2 A2 Z7 k3 |8 o* y
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函数必须返回一个值7 h9 g& y, l+ y% ]9 w5 c+ F7 L
B.reduce_fraction函数必须接受一个整型值5 l4 U) o0 N7 [  s; ?) u9 V
C.gcd函数有问题$ L# u, d  ?& Z, X/ \( I
D.必须通过引用的方式传递$eight_tenths对象8 Q- v0 w: m' f4 ~
E.对象的实例不能传递给方法以外的其他结构。
& }- E$ o9 t  P0 Y
( H3 ]- {+ r5 x* S9 u  X% x# e1 q+ k# s; K' `
15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法% X" [& i, z0 W, Z% j5 r0 o
B.生成myclass的实例并调用mymethod方法
# ]& W$ b6 ?' GC.产生一个语法错误
( n! q' h) M. f4 r3 ~" J3 e/ c* D) JD.默认myclass类最后被创建出的实例并调用mymethod()! H/ ]' [. b% N+ J- d! w9 k8 D
E.调用名为myclass::mymethod()的函数  z  Y! t5 S. z0 r; l) \5 ?; `& B
) x5 x+ ~* ^8 N* V$ D# `

5 B9 X5 ~  d3 n16.PHP中有静态类变量吗?) `) V& d+ E% M9 R# r5 m% p

! k, {+ Y2 s& v* I- |A.有  h3 `& _/ n' J; V: V4 |- }8 V/ v
B.没有
8 H4 G/ b! O! f' f0 }3 F6 _$ a9 @% m) b: a8 `; R4 b& \
" w: ?! T3 |. W6 c5 k
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" ]- i/ _7 t( e: A) L
B.2
& z7 o, b+ j. T! j" zC.一个错误,因为没有定义a::$myvar. t/ I! g4 g/ j7 l- L6 a& x1 |
D.一个警告,因为没有定义a::$myvar
! I8 \  T% }; e# j8 @E.什么都没有6 u/ T2 g. n. O% R

, v( Y5 i2 U" M0 E( r3 w% v" {8 x& Q9 @- G# W3 y% \4 x4 D- w5 i
18.如何即时加载一个类?0 r1 A0 x6 S' v) z: S- h5 n
- n- r: |$ Q8 Z6 c
A.使用__autoload魔术函数
/ `! \% a9 v: cB.把它们定义为forward类
# T- `. t7 H& C9 T+ i4 D- MC.实现一个特殊的错误处理手段
. R1 s5 V( x' _0 JD.不可能
$ [5 B) r3 q" I$ H/ v) Y7 KE.用有条件限制的include来包含它们
/ h, D% e) `" d5 a' b* x4 x$ z5 `. r& q# x4 s- z$ O( \+ k

/ T3 M! c5 G9 S" y6 h( F: b19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?$ j# k+ m0 E0 u* A( B) T6 |

! z2 \3 Y( U  k    答案:__________* {$ r& a* c! b' o
: H5 M" a3 \. T
. h9 H  ?. ?5 i' M% n4 N2 \
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) u9 i; ^" q9 K+ [! g: @1 ]" o
B.一个错误
: W! ]2 i" }2 _C.一个警告
0 M* x) c1 l" B! u) W% H) c& fD.什么都没有
5 Z" F5 `3 M& r+ P: w" n" K( M' v* ]
8 a0 B& D( \: d( z& W& V# K7 @/ B# T$ A
' Z3 \7 k' O1 W( ^1 s; \9 [
答案速查
6 Q7 z+ O% @- x0 W+ q* }/ E1.类
0 J9 u# l( R' [7 i# d& S5 p! `% H1 ^2.BCD  s: n( j2 k' W' ]
3.C. n% H/ a& H; p8 O# [/ j5 \
4.C
: ?- O: P0 m- p' n4 Z0 w5.A
; |8 K& B4 H( ^3 P" ?6.C
% q( b2 F, ^, {* v3 X2 I# V7.C
! n* k( {! x& R" j2 p$ L8.C6 u" X( Z, U+ l  F7 y: y
9.D! [. _6 W1 @( y: O/ H6 w
10.B( D! [* A2 z4 o2 h0 b& P  B9 H
11.D
7 s3 d+ E  z/ @* f$ W$ H" o/ }# @# K12.B
8 r" B, E. D) z. n13.A# z! y& G/ E; a! E, x+ T5 ]7 d
14.D
2 @) T1 b& E' ]' |15.A2 F2 f4 y6 Y0 b* S: ]2 {8 `& T
16.B
! ?% y# h" [1 L! O17.A4 ?5 r) u8 n8 [2 q2 V! I
18.D% ?! L  z4 |' H/ I( e
19.设计模式7 R5 k4 W" l0 F- k
20.D$ O9 g( V$ j# R: s1 H" _
0 n# d& m7 e' b% |' p4 c

. c- W3 V: ?# }( |' V/ G) R
; ~( A3 z. h, V& `答案详解
- I5 `6 a* {' S( v! o* ~/ {; P) ^8 T' b
1.类是对象的蓝图(对象是类的实例)。
" U7 W  m/ [$ y3 [; U' b
" Y- d: G. I4 U4 \# J2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。' [/ a; A0 q9 V/ y

* M8 E7 o) J6 ~2 [  L; C3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
9 d. ^  R6 A1 s& h8 `4 d2 j7 F5 {5 |5 h0 ~' q, g1 K& f: c- l9 @; B
4.单件模式可以限制一个类被实例化的次数。
4 ?( w2 x% p- K, a
7 m) L9 z: b6 x$ x5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。8 `1 E' Y: b4 M& T% D* z

  }/ U2 n' u$ R- G9 H6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
: M% S6 Y8 i7 ^0 S2 m2 A& U. {7 @. L
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。& d% H  z" A" Y9 ~

) m. y: C( Y! q& b( ?8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。$ T& S+ L/ Q, R" s: F

5 w, ?9 y2 \. G" _0 q$ e9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
; W0 f9 \# U& a2 V& x; H  C5 ~+ g: L' s7 [; l4 D
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。6 ~; A" T  _3 z7 w& Y5 k* }
2 E$ A0 V& G6 b  w2 t
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
$ z0 I9 Q( M. @5 }" `2 D( ~0 L( B
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
# J- u2 u* B8 {( e& z: Z5 O4 w6 }5 w
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
) j( B# R2 o" n2 W% }  r( l/ M$ \7 w; I* N, @7 C" {  W( I& ]( J
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
" l2 |& V4 f+ a2 H  r- d回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
% @, `% P- e# D2 J8 `3 V5 z    function reduce_fraction(&$fraction)
$ F" {, G3 d1 B0 i- e: A& I5 D' ]2 w答案是D。- D5 O* a! H9 ~  F

6 x  [  {. J$ h15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
6 M7 w0 x- p+ L, {2 ~0 ?+ _% u6 Z; \
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。
8 I1 A5 G8 k7 ^8 Y% m& \& o# B" E; \! |: w6 X' C) o
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
: ^- z0 z( ^5 X1 J  P- ~
& u, N) y! B0 H% \3 t0 r2 M$ x18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
# S( `/ R. j6 w1 Y1 j. R# w; S1 |$ v7 g7 K4 R1 H% X! K
19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。: h' W! P# f7 x) S% n
6 I  K+ H  j4 ~
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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