返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
9 b4 G! P# K5 \8 i/ w% LPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。: ]' R3 p1 l/ s: E1 k; T& u0 K# j6 J
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。/ [8 U! r' ]5 ~, F# {
! s  M* s* C  \9 V
问题9 s1 R  G' i" \

8 U6 \5 j& }# F: A  \6 Q6 e1.对象的蓝图是什么?
+ X- m8 j* v8 _! I* ?; E! A# |' T3 {+ T
答案:____________6 D& j0 n( D- @; j2 `# X# _

9 i! m: x" z/ y
7 v4 V8 z3 ?3 ?. w( n2.以下代码执行后,数组$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
7 R$ G) Y* d9 |B.b
/ o5 M, y( _9 i3 M8 l$ M/ m2 uC.a
% }: a- d& `5 M" I6 b4 GD.d! L( z  T" O% d, B6 T
E.e5 O+ L4 H2 D& P

( k/ v3 q9 ]5 o! w4 C! c# m7 b
! b2 A/ N0 `: o3 p3.如何让类中的某些方法无法在类的外部被访问?3 \+ v5 B- f* o1 h% k7 d: I( m
$ H3 j/ z3 L; L. ]
A.把类声明为private
+ K7 A) j* M. H" x$ k. y2 ~3 XB.把方法声明为private. v4 m- T' S) U
C.无法实现6 q- e  y& p5 c  t4 B
D.编写合适的重载方法(overloading method)% u$ b5 m/ j$ K  N; p
; X. c* L7 U% O. T* S
8 G. `; u( k, f: s, C
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?% R& ~( o+ C5 C0 f- Z

# L( v) \/ O; @6 ?A.MVC模式6 m6 k  N1 j2 ^4 i. x( X
B.抽象工厂模式(Abstract factory)
' O2 i/ ^! K9 g8 i" E$ FC.单件模式(Singleton)0 M' d+ O9 e7 i+ F8 J- E/ T8 j7 V+ |
D.代理模式(Proxy)
- j! a  w8 ]2 `$ g4 L$ \& v* YE.状态模式(State)9 I  g+ c$ @6 @5 K( m9 ?5 h1 p; ]

6 V; L9 `' {; r3 E3 @" Z) t( j% n# L$ T: p4 H3 E7 Z. ^
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?+ s3 X. r* I( ]

3 d; d5 ?+ S" q3 {: s2 JA.1个" J4 Q: E; {$ U" B/ Y
B.2个6 G9 k! @  P- m7 E3 {
C.取决于系统资源. _2 t2 ^7 s5 U& X0 S, v/ O# j
D.3个6 f5 l! Y1 j2 [) Z# K! {
E.想要几个有几个" T! z- v0 R2 r, k# Q

% t" n' G; l  O7 k9 H
, p, D! u6 M. Q3 i5 a, d4 G6.以下脚本近似的表示了一种在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.多重继承
! R2 n' u( B' e3 a5 G* tB.接口4 {! L- S1 \, h0 c* V
C.抽象方法
! o  |/ k4 r2 O) YD.Private方法3 G1 z0 D( E+ v. j- E6 D( w" D
E.函数重载(function overloading)1 l, K7 R4 |/ u7 D* K5 c5 L8 e
) q) S0 r( c+ Y4 ]6 j% _
8 H' H5 x4 L2 K7 c; x' I' |0 e5 `
7.假设定义了一个testclass类,它的构造函数的函数名是什么?
. b; w- R& T& L7 ~7 L
5 ?9 N7 K$ w2 F# eA.__construct, X; h& T0 T5 c2 E( U, b+ d
B.initialize
' ~: F9 E- J0 E% y) zC.testclass5 E! T0 \5 l5 o) J6 K5 \
D.__testclass0 q+ t0 B3 v9 I# y5 \
E.只有PHP5才支持构造函数% w5 ~1 K& y9 G$ _+ Q7 M
6 b* D: R7 `; y! P$ T! [

9 v4 h0 V! I' C+ @- Z8.一个类如何覆盖默认的序列化机制?
6 ~) T7 H8 \6 k$ ~& `3 `7 K% S2 A. S. I
A.使用__shutdown和__startup方法( z9 o! Z+ K6 e$ z+ G5 Z2 h
B.调用register_shutdown_function()函数1 S3 J) x9 M7 ?- ^2 _
C.使用__sleep()和__wakeup()方法2 G- \0 {& N$ z" M" d
D.无法覆盖默认序列化机制: Y  I+ w; m5 \" M# C
E.使用ob_start()将类放入输出缓冲中/ x1 g' M  `/ {2 b

/ n7 e2 ?0 ^1 f) q- ^' B' B0 K0 d; o2 m4 m/ ?/ }
9.以下哪些面向对象的概念无法在PHP4中实现?* Y' J' w$ i/ O8 e% l

, R4 @& x4 @$ s& @& ~8 W@抽象类
/ P7 t( w8 H- u9 b, J4 O@Final类2 V9 ^9 e0 d5 z( [9 f
@Public、private、protected(PPP)方法9 r4 Q, }# F( m0 o4 i1 |# D
@接口
3 D! Y! O& @! S4 e5 M) \/ w$ ~$ }4 k9 G! X! u/ s9 B- ~
A.抽象类
: x( ?# W& e& U- e" cB.PPP方法
6 ^0 C" v7 x* q8 ]1 D1 \C.PPP方法和接口& ]$ v5 t. K9 }$ y
D.以上所有都不可用
6 W' `+ w% t  n, v3 |' C- s1 mE.以上所有都可用
% V  F( G# Y% G6 w7 l' g4 ^) }9 o& }& [; B! C
+ q5 n9 }" w$ R* v: a& Z6 j8 _
10.如何在类的内部调用mymethod方法?
# O* u& Y9 h$ q( V1 U- X# R' Y
9 e1 {1 M- n' L" xA.$self=>mymethod();6 \3 _$ Z9 _1 S6 Q9 d- _7 t
B.$this->mymethod();
' _6 ]. t/ W4 }& I0 K# R, z: G- PC.$current->mymethod();
% J8 |9 u  _) g% Y6 }D.$this::mymethod()! P" E4 t3 d3 e5 ~7 b6 t% G
E.以上都不对4 k+ F/ O8 L% ]4 C4 z& p
4 J( ?% J; w6 n3 G! u. U4 `! @
- y* X3 d+ g# O
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+ {. s. Y6 h0 U( K
B.Null
6 m& L9 Y) O. H. n/ Q) d) x" E3 oC.Empty0 W# j3 S7 B6 S; Q5 `
D.什么都没有4 |2 Q* v3 S$ B7 f0 |* w- z# O
E.一个错误7 n1 S# U) U9 m  A& ~7 B" w/ ?, H

) a9 t8 G; i/ `. m) B
. w, q) ]' W* D0 J12.以下脚本输出什么?

  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* f; I- K4 V: t8 o8 W
B.5
0 e) ~7 w9 P" k. m3 g* aC.24 I+ W2 r* r' q0 `  Z
D.Null
6 E9 O/ N% D8 g' a, {/ xE.什么都没有
6 W1 B  ]3 B2 V4 {1 h) K( D! `( y. l1 K! L$ Q* I* F
! h+ s4 v0 I# o/ I+ @8 J; G
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. h0 a1 w6 l' q5 [, a& p3 a+ w
B.10
4 U& \) m6 F& L4 ~C.什么都没有' M$ \. q0 I: Z. _8 J6 c# _' `- E
D.构造函数将报错
+ z7 Y% `* o7 PE.510
* g' O3 u+ d1 p  H2 g  i0 b0 Y
3 z+ @6 x7 E" J  O9 \% |; _& _! W- a( ^) j- J; u: p6 i+ x1 X4 x9 m
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函数必须返回一个值! b' `4 O+ `0 h% O$ t3 ?
B.reduce_fraction函数必须接受一个整型值
/ S$ [7 b' i, x% B9 `3 Z; cC.gcd函数有问题
+ x* n- ]; l% d3 I, BD.必须通过引用的方式传递$eight_tenths对象
% `: D# A7 f3 p1 u/ Y2 g. n" k. uE.对象的实例不能传递给方法以外的其他结构。' r8 C1 w) m; q% {
. L# B" A  }8 g: k- `

, B" r: }6 V& X( ?, l% l/ e/ K# T6 D15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法
2 z( I. P( t  p- Y, eB.生成myclass的实例并调用mymethod方法
# {3 ]. Y! s" ?2 w) h1 J  p/ u9 w$ {* OC.产生一个语法错误: @+ J7 C6 \! [8 L7 B& \0 f
D.默认myclass类最后被创建出的实例并调用mymethod()4 {7 }" y% S/ Y% P* T
E.调用名为myclass::mymethod()的函数
9 t* X8 \/ o  C$ Q& T
2 D) j7 K, q# z' @1 e
1 ^; _/ f1 o  {6 a/ o16.PHP中有静态类变量吗?
% k7 @& U+ y2 g1 K! M/ Z5 Q  _
( M* \' B  _6 `- T# }A.有" D8 C7 N  y# u. Q
B.没有
& }; |# n9 M/ D% Y* v7 n. O* M' K4 Y  G4 U
$ P8 ]/ ]$ k1 U# g6 F6 E' V
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.14 [. |  C. P/ o5 s
B.2% @# J9 J8 K$ I
C.一个错误,因为没有定义a::$myvar+ z# P. B. J5 p
D.一个警告,因为没有定义a::$myvar
% \7 n- [& ]# ]4 y" {; wE.什么都没有5 J" u' S0 t# V" o8 |5 w
; P1 j# y+ j$ ]5 b

3 r- f# @6 n; G" p6 V18.如何即时加载一个类?! @! m+ j( ^5 u3 D% F; M" X2 J

% a  z1 h. a2 n5 PA.使用__autoload魔术函数: p. t3 ?0 D9 s! Y1 |" j, Y; t, X4 A
B.把它们定义为forward类: c8 N$ v- @: p8 b: B
C.实现一个特殊的错误处理手段4 v* s3 o  ?3 B; h& ^
D.不可能
1 `& X; }5 N! [E.用有条件限制的include来包含它们5 B6 n( T8 }7 a' i
9 v! Q0 {7 J! M; ^. X1 Q3 v
0 \6 ^1 H% D! ^9 I
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
1 x8 `2 W4 t# J( O4 L( s6 ^$ a: p% _6 z% _1 E5 {
    答案:__________0 R# y! ]2 }3 o. G& I" M7 W! G; N

0 C* K; E# [6 v4 h: A1 v  P
6 s. ?0 B1 Q/ ~  ~" M2 N! J20.以下脚本输出什么?

  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* `7 k5 }% H9 Y& D. v  G7 A  l
B.一个错误
7 S$ U9 |% a2 p  V' D, j# ~C.一个警告
7 h: [1 t* I5 ?( nD.什么都没有0 @. w  I# V9 U! E% q  X% h

& M" ~+ }0 A+ n3 R8 @' d! N
& K) J( x% }1 B4 \8 A' N+ P' N, A: E0 O# y. Y5 b
答案速查
3 y3 i1 w. V4 b( O, @% H1.类
9 b9 M; N5 [4 X2 ?6 s2.BCD* R! B' W5 Z& g: @3 l. k% j' s
3.C
- n2 r% G" B; U$ T6 c; }6 T4.C0 t8 {7 P* F; g7 J) k( l
5.A
$ m+ d! ]) I! }6.C8 @* [3 I/ n) D$ J9 ^
7.C
$ f5 ~  S7 }- {) }7 O6 ~" W8.C. d: q$ z- g& g& q
9.D! G% I! C, V9 k
10.B
& N3 a2 u6 u, z11.D& v* h' @7 j3 s. p/ d$ B" @
12.B) K* l* i3 J" B, H
13.A4 q  f8 s" @! K7 P( W( f
14.D0 d* u5 H: k4 d" l
15.A
% S5 H' M. `( t: W2 Y- ]/ }! q16.B5 Z# {! z( }$ t, x
17.A
# V1 F4 s4 j, W0 i; k18.D" A# \% P+ Z1 f4 U# |* u
19.设计模式
8 g  E. [; ^6 o# y! P/ `20.D
$ o4 i7 M8 G6 W0 Z
3 I! A; _# V. V* P6 s) A9 |! I+ r! K- f( t' J2 {! P# Z
7 X  t6 R9 X7 V4 [' c% f0 u
答案详解0 @, l6 U' c2 g9 T

; @# i# C* q( i# u/ N: X: d; O1.类是对象的蓝图(对象是类的实例)。
* t- [6 ~/ J. _4 S+ V1 T. e  o. W7 a5 N/ B* Q* A+ Z$ ?
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。
; |5 Z4 K# r( V7 `8 [0 j& w5 }4 O5 G6 }% W
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。' D: Y" g: A% n) n- d5 q

: `; p4 {5 L9 A! A: z5 V, B( i4.单件模式可以限制一个类被实例化的次数。- h! s0 f0 X/ f2 `6 U2 s
3 y& u0 F% d& A2 p
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。
7 M% q" Y+ F, U
. {* J1 o; [6 w4 e3 H6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。" i7 [% l7 p" c0 b

+ |" t  h" c7 w( c% b9 e7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
9 }; ^' J2 J7 a: `* v  q: u" K) ?5 }. [: c0 S/ E8 P' F" G
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。: [9 B7 Z( O) t1 ~3 x* i# A) K$ f

) `/ E, g+ r1 Y2 y+ [5 ^9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
6 v, _+ H' W2 Y, s$ ?; [
, n+ a6 b- h6 ?' H) @10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。6 Q  v$ @6 ]  a: D. q' {% _5 i
8 }8 K% X7 |3 x; A$ l& x$ {
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。# t/ ]. V. A  T: n0 s0 K7 T# g

$ X6 M! [+ L% H! g- V12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
4 X) z" K1 g! b! Z9 T
+ U8 G- {" o# D4 |5 w/ X13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
0 d7 \6 ]) Z9 _0 I9 N$ K, D: h5 T
- _, d" h' Y" s% T  t2 q; B$ Q( U14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
4 Z5 Y4 c9 M; G' Y回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:7 B+ ?2 U+ p1 N
    function reduce_fraction(&$fraction)
8 n' k: a  z4 J$ t# i6 Z2 e答案是D。
! t$ C9 p  O* U& K8 O7 M7 ?/ G
$ ^4 f6 G# {# T4 h) Y2 K15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
! U8 w: J* ~/ c. e- y4 l, F4 U- g, `: J7 x
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。" \! s; [9 d( v# E2 A# M: c7 W8 l
% H. Y. H: E- K1 g5 H) E
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。/ Q! A  h6 [+ R
$ B$ }0 d1 y# f+ L' q  h  f( {( B
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。% I" _# f, Z& t6 V/ I5 g

- k! B6 P( W3 @- C. ~0 W+ x19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。" N9 k$ x/ n$ }% A: g
7 s7 L- F* O% J- f( n  V4 u" a* Q
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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