返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。' k. N' ^5 c- k
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。/ X) T. V& R$ H8 o
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
. d" t; o& k" S1 Y$ w7 N4 y: w9 C" B) _! e; U7 J
问题
) l$ e- E6 J5 L7 a' P" m& _1 c( U+ S
1.对象的蓝图是什么?" [: u. L2 B- s) f* f1 _0 t7 [8 I
. t8 `. y1 p& a: y& P2 |0 R
答案:____________
1 Z! V, U7 W) D1 ~$ x. g5 _# t1 Y, z% Q5 S7 q) \
# F1 e6 r( r+ }# R3 s- a
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.c
- }4 _4 h, T1 N( n. h: ]B.b7 S" J  W: {. W& P& e. t" c
C.a/ Y6 d+ ^% U8 ?5 c3 I
D.d
& L4 w' m2 |; @' m% FE.e
' N& Y+ R7 r- {
7 y( P2 S! l" x2 u3 F( t- n! w7 H4 h
3.如何让类中的某些方法无法在类的外部被访问?' Y6 d% ?8 r( L2 A3 {

5 X$ c/ J- a0 A5 s9 MA.把类声明为private
; _, {% M2 n( L/ `* ?* OB.把方法声明为private
8 f' {0 v) p+ HC.无法实现3 C, Y7 p7 [4 f7 D
D.编写合适的重载方法(overloading method)
8 b$ n0 t7 }( y+ @
- j5 b  }8 j% h) X3 O8 g+ k; ^* R' y
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?. q0 B' r2 {6 {, L
+ G4 U; _4 K; O0 Q2 v/ p
A.MVC模式
/ _; R: n" v+ a3 I$ M  h2 H/ ^B.抽象工厂模式(Abstract factory)6 z5 p1 i6 {% c. @, a
C.单件模式(Singleton)
9 G7 w. H* ?. I: Q5 |5 w( ID.代理模式(Proxy)* H  U  V$ t- N
E.状态模式(State)1 i5 s, E3 d) \5 P" X) c& g

: y; c; ?& R5 \4 N. F/ d5 l3 @6 r, H6 \# a
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
. d9 W4 H6 ~1 D: a" v; U- v9 X
) }* ^7 Z$ Z; t0 V- e! t0 i. wA.1个
+ F" I% o2 J7 s. kB.2个$ {0 S+ x6 P7 P( }
C.取决于系统资源1 {0 R  j$ G* x
D.3个
% s+ e$ f! E6 ]# T( ]) JE.想要几个有几个
! U7 p6 `! y0 Y0 U+ r) l. z. B+ c' N' Y8 h8 M5 w0 p, G7 @
& a( y0 ]6 S, f& ^& X
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.多重继承9 h) ^, S- N0 O/ }
B.接口
- d9 i' l- _3 M  MC.抽象方法
7 r# u2 _/ P) \8 _4 ZD.Private方法0 [+ O6 A. p1 A; c7 d& [
E.函数重载(function overloading)' y) n0 Z' i! K. d! d

# v, o1 T0 Y. i  D
* X3 H, y2 P2 x3 C1 J7.假设定义了一个testclass类,它的构造函数的函数名是什么?& I, O0 A- M& \, d; E  _" A
' O4 M) u9 a, w+ F5 I, r% Y
A.__construct
+ |7 k+ T# K% |5 C1 r" r' ]B.initialize$ t% f! \' Q' G2 y
C.testclass! u$ w- W8 I! t) A
D.__testclass
; b% \. \1 z+ e) Q+ j% ^9 k- rE.只有PHP5才支持构造函数
- ?# ?4 A" L+ l: e. _* e. ], W7 }/ P; |1 Q

) e! `) `# Y3 |4 P8 b2 W- C8.一个类如何覆盖默认的序列化机制?0 s& [  }: g- G  E
0 x5 Q9 Z. b- y5 x, ~
A.使用__shutdown和__startup方法
! p/ ?  f) @0 W+ e% q9 L: U5 MB.调用register_shutdown_function()函数# d, k* J  O5 R+ ^+ i9 M
C.使用__sleep()和__wakeup()方法) S( `; E6 E0 l* o, a
D.无法覆盖默认序列化机制- Q9 Z+ n! z  s' @3 {4 l
E.使用ob_start()将类放入输出缓冲中
1 n. n  P) ?* H  Z& O) Q* w
/ m: n! j, {" R+ Z2 @3 C% m* `5 ]
) B6 m5 i! j! a0 T4 K& t% w- n9.以下哪些面向对象的概念无法在PHP4中实现?
" h3 I* a* {% i6 j# @7 @2 ~0 }3 n5 Z# K$ x" b2 u2 ?3 U4 |
@抽象类& v8 B/ D! \. T% \2 `
@Final类& F9 l  R2 v$ u0 a" V* a' j' [
@Public、private、protected(PPP)方法: t7 g4 m+ w$ k  d
@接口# x# _) N- F9 @- N% I/ d1 b- [+ C* P5 v
/ E3 v. X' `* I
A.抽象类
" |/ d+ w; E' E  @& z9 [9 ^B.PPP方法; D9 c- u6 A& v9 |# f. n5 ]( i
C.PPP方法和接口& J/ x- T! F9 l- b7 L' ]' e
D.以上所有都不可用: ~% M3 E5 W* x+ A$ I# t
E.以上所有都可用( {) g7 Z% K% U% z8 \

! k) I$ ^! F8 O4 Z  _$ n: B/ g% ^1 p" U. u# G& w( p0 `4 o8 m6 b% A4 S, \
10.如何在类的内部调用mymethod方法?5 F7 M- S/ r$ ?! s" _# Q! h

0 _8 t- x& k3 c! }8 NA.$self=>mymethod();1 j9 `$ m' C& P- t" t$ M& D$ J2 n
B.$this->mymethod();: Y# ^/ |5 s/ f* v+ b& [9 ^4 Z
C.$current->mymethod();7 g! i1 N  S% g2 L3 e  P2 A
D.$this::mymethod()# ^; i8 E6 T* b9 v
E.以上都不对
3 i) ^. c% m  T, w3 W
7 M2 b- y; `/ Q! F+ i( ]; j
' t" S3 G" {% K11.以下脚本输出什么?

  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# m, _( L" E) }; w' h
B.Null
) s7 y' f$ Y' t8 @! `C.Empty8 z. Z* |. j& l) H& |
D.什么都没有
7 |1 P2 _9 w+ B9 F: zE.一个错误5 I7 d2 d- x3 A  @7 Q! z

. k1 l" i7 K% F( s
3 p2 z& f! v- D! S- X; P12.以下脚本输出什么?

  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
. ?7 k# _" e! aB.5
4 }) {- Q2 a# ?7 u$ j, U: o/ l1 O' j+ SC.2. p8 T& m4 C, W
D.Null
! B! {9 H0 m& A+ ?, w- {& }( PE.什么都没有
& R( {4 r+ l# K) L8 c+ w9 f6 P

  H9 l. q; U7 n3 _! i) R13.以下脚本输出什么?

  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
9 c+ J/ n" |" A1 q1 UB.10
( |7 y3 V* n5 O# |9 U& O2 AC.什么都没有
9 G5 S: Q6 w4 wD.构造函数将报错6 M( r' }- g9 A6 A
E.510# C3 s' u+ d$ A1 X

' R7 z3 u7 n5 D% q! ~' X: {9 L5 c$ Y9 k0 \  h* Y! q& t
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函数必须返回一个值
1 {; v2 k" X1 }8 H/ gB.reduce_fraction函数必须接受一个整型值: W- F$ ?. m4 N, m$ Q4 v9 N
C.gcd函数有问题$ q- r" V( k" q/ h; _! l7 j: N6 ~
D.必须通过引用的方式传递$eight_tenths对象
3 E% f) R$ B) YE.对象的实例不能传递给方法以外的其他结构。
! w5 O. T, B& ~& U2 [; ?* u& F" F' b$ {8 _2 d6 B8 M' Z, e% a
( u  T9 j5 N7 X4 q
15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法
4 p) l# Z" v4 U* `$ XB.生成myclass的实例并调用mymethod方法/ z% K! g( {2 ?
C.产生一个语法错误% u; Z) ^7 L8 E7 C! ?; A1 L, t9 B
D.默认myclass类最后被创建出的实例并调用mymethod()
7 ?9 X2 ?& Y2 _. |E.调用名为myclass::mymethod()的函数. [6 G( j5 I# t; }# b' |! O( N

* {. x5 k% f# k+ `+ R: ]* {5 L4 R5 H+ L/ w% Z, Q5 ~8 D  F6 K
16.PHP中有静态类变量吗?
6 [7 k: J) y3 T6 _* S; ]  v9 k: Z% M7 e4 M) R
A.有9 ^) ^) s& w6 ^- r8 ]7 M+ ]
B.没有& h9 S/ a6 ^3 u$ ^! _( r

) @* _" Z, W2 L
: Z" u& h+ Y# s4 Y4 V17.以下脚本输出什么?

  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+ `! w, _) h- |, \3 X2 ?  C" Y
B.2
/ V% P) ?$ P& c' V+ R. c# jC.一个错误,因为没有定义a::$myvar4 e  C6 F1 V. P6 W. Q4 h6 `( P
D.一个警告,因为没有定义a::$myvar
) J  ?# [, |6 t# i/ ^E.什么都没有
+ Q$ ]' K/ h# {( l6 f; ]  H
0 q$ \' @& P4 p
% L& q' V: |' m( I- y% K: M18.如何即时加载一个类?
: f% z3 w& S& I2 F* P0 f& Q' K9 _+ m: K/ ~$ X% p. X
A.使用__autoload魔术函数
$ n# ~- P; p; m4 N9 ]B.把它们定义为forward类) t/ U. l  U; H; t9 x/ N
C.实现一个特殊的错误处理手段, v0 m7 F* [& E
D.不可能6 P1 Y) V+ l6 J( c+ b- v/ k
E.用有条件限制的include来包含它们/ z9 p4 d3 F9 u# u5 `
1 q: Y3 |3 S' k! P  ~' c, D& g

! F6 m& I) C6 y9 J$ H/ x  G19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
% x6 I/ P* @6 b  R$ S8 b) v8 I7 ?  g& ]
    答案:__________% u* n/ z7 e$ U3 C  ?( s& Z* P' U9 r! |

1 ~: J( ]" g, d0 |
4 @1 T7 T4 i3 H20.以下脚本输出什么?

  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& D$ u! |8 Q4 }4 q( {
B.一个错误) w0 e4 d0 h: @& |: v
C.一个警告
: x: `5 R' y4 @# ]5 dD.什么都没有7 `; t" Q. L$ X& j

5 R5 s" x: _+ i, k; R+ e9 v6 v8 g) a' w( y# @3 \' @6 M, R2 w

1 n, W# y, h& j1 M' M答案速查. ]! x: d8 k' ^  a% \$ Y
1.类
9 R: T: \' A1 F7 O. T2.BCD
% [( y1 ^* d! J( e. J% {; W3.C
/ z8 v7 C; `6 h2 L' ?4.C
9 n+ [" l1 q0 B% O- B+ j. L5.A3 y4 v' S1 n! ]6 g. W1 V8 k
6.C- b; ^/ l+ h' B7 v  \+ p
7.C$ i3 v% d" _4 ~* H/ u
8.C
8 j7 }  {; r" b! O0 \$ u9 b& H. {9 q: t9.D! c2 ?2 g, b3 ?
10.B8 I1 E3 m! g( V
11.D$ c  u* O' g# M3 R
12.B2 d1 x) |: r' P# x  J
13.A( |6 X0 {" n2 K( t
14.D
6 ^8 y7 ^) \, G. |5 L$ j" t15.A
# ^1 _! Z3 V$ h  j4 o4 {- H  E16.B# Q' W% ~+ G. y8 x
17.A
  C1 A) a9 }4 a6 |" W18.D3 E& Y2 b) O8 n7 W' \: ?* n
19.设计模式
) Z$ W" m, w1 L" W20.D/ d" k% r1 J. |
, }; h6 w, h/ w

$ ?5 b& `4 G+ V0 `+ ?; q# z7 D) Q7 i
答案详解
  k3 @  x$ P2 G' i, R) n, ?/ J
4 K- ?- }# C& E! f5 k1.类是对象的蓝图(对象是类的实例)。
4 R' s" v# {  q* L% w# x" O' x9 p# B! G$ Q# a
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。( t4 Z/ A1 l8 S+ v0 V) b

% {$ f" h1 k) }3 i" c7 m3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。' I4 x. ^- i: N
: S* v$ ^1 u1 |+ e- J
4.单件模式可以限制一个类被实例化的次数。
4 j3 r6 k! d6 h! t6 x6 t8 u- H, A# ~$ A1 t
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。
. i, E% D1 G( J
1 i, V3 f3 [& Y) F/ O5 J" |6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。' o4 `7 A6 H2 Q/ l
  w4 Y* V+ u; ^
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。! W$ I( l' m4 p! P# K. U2 K
0 Y) A( I, f0 e' J& I
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。- D1 V8 H! H, y; I
" B' `0 q# }: F( t1 F. O
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
0 ~$ a( @0 m* J& v( E8 ~% e
/ F) H) A& y8 q6 P10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
, c/ Z4 a$ k: M: l# E
* f- {2 I# q. n9 r- _8 D11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。( ?8 B  O; R0 |
/ V. p; D" D2 o7 S
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。6 u4 w: E% r0 i$ t5 F7 A* G
1 R0 v9 t4 g8 M$ h% Z- d/ b! m( d
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
: {3 F8 v- \7 P6 F- C
/ \2 i/ t% M& _- u, H2 |, f; ]( {14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
% S: r) \( ?& x6 f! R7 n, ^$ c回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:$ M7 t2 d& C6 I' M4 J* U
    function reduce_fraction(&$fraction)' _! w4 D2 K: t
答案是D。
- T+ S/ o7 _- I1 l# i8 A; G( n4 Y( x9 `
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。9 S5 s: K# o1 {4 E
8 Q* [9 z$ P& `+ A; D6 M
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。
6 x' ^$ l' D  b; o5 F6 q9 j% z: L0 n8 G  N
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。$ ]7 w+ {) k) E: M1 h
1 ]# Q2 W: s7 C. G/ H* O
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。  P- ^# y' ^; Q2 t3 y

: B) L- P. _% I19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。- Z2 n2 i. y1 l" ^

; O& }$ C5 p9 _% {9 Z7 F. ^/ e3 U7 ?20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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