返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
& u' K4 }" m. E2 d1 z$ APHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
1 s0 I; p: s" k9 R本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
+ F* X5 B+ |" V. {  `6 ?
$ D% c: q- o! v1 g# S问题( `* C# c+ d: G) Z* E
# z0 W. C5 g* Z' o. J5 A
1.对象的蓝图是什么?
8 F  Y7 }( B3 p* j2 q. _
5 \; B) I) D: Z( v, W+ E答案:____________
6 b2 {/ c, D, i
+ r$ a) ?6 O3 R0 F& ]
- B+ i& u" f% p9 x% P/ O- 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
$ m9 |. P& w! W6 _9 p4 v7 pB.b
: y: t8 x/ @# sC.a
9 e( e- j8 M5 [4 S& jD.d
4 W0 e3 H3 V# g7 g* f8 ?E.e
: G( S! g- F$ q/ N2 b  M
  W' H; M0 n/ w9 p) M" |/ ?4 M0 \+ A+ U5 X8 A" K2 v4 d1 A
3.如何让类中的某些方法无法在类的外部被访问?
: @- l, a, G( u' c7 {
5 E- ?7 V; l& ^$ s/ C& W' xA.把类声明为private1 v7 Q  r1 A9 b  _9 j
B.把方法声明为private$ V1 l: P! U# M$ g. j. [- Y
C.无法实现' I6 o5 J1 [% m
D.编写合适的重载方法(overloading method)
; U+ B" ]2 K0 ]. e7 {  |) i& s0 q, B. }  y3 U4 ^- {& P( A
- \" h' H+ A3 Z& `1 f
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
& B) Z4 ^! B! Y/ u- g) Z# j
. Y% p4 [2 _2 r2 N% nA.MVC模式
5 u4 ]2 D; x# `" a2 gB.抽象工厂模式(Abstract factory)1 i6 V. v( r" m  p% v
C.单件模式(Singleton)5 C+ M9 z) y% ?  W7 t
D.代理模式(Proxy)
) y% ~2 y% K& u" a8 d6 GE.状态模式(State)* f9 f( [: e# n- T8 G

1 I: }$ @+ w& @1 W" B
8 @  S7 y, d+ _  [( ~; v* W5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
' V/ f- r$ s7 k( h$ [# p! n7 r8 Y# Q! d
A.1个3 i  i9 ~8 J% X7 F* {
B.2个7 ]( x1 u$ J! |5 z) x; X
C.取决于系统资源# |8 K* _: q: t  _9 E& X% e3 h
D.3个
4 R# z  G8 N7 }- D. fE.想要几个有几个) r! M% T% u1 z; y2 G1 G
0 C  ]: s4 i0 |3 F! s. a0 F% w3 c% P
9 w, @0 a1 r$ d6 ~' J6 W
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.多重继承
- |" b' A) r  N+ aB.接口
* c: O) G1 [/ Z* iC.抽象方法
1 }) n$ f, @8 w( @( I' l& LD.Private方法; u4 N$ u; ~1 j) ?; w" y5 ~, V
E.函数重载(function overloading)
6 j4 Q" S4 u+ k
9 ]9 ?3 G$ i' D9 @* F6 N( M. b# t5 b' o- x0 E/ a  ^* M9 U. n
7.假设定义了一个testclass类,它的构造函数的函数名是什么?7 _9 G: H! }, v
' S- h/ d3 Y$ @6 @
A.__construct( H# x3 ]) f- h; u
B.initialize
8 T0 }8 m/ M  A1 k' Z! X' OC.testclass2 J, v: a2 k) a, ?$ K* ]
D.__testclass
+ v% m0 J) e+ ~! b- m1 J7 M9 x; qE.只有PHP5才支持构造函数) Q4 X6 X0 x1 e

: J5 }3 D, s2 J+ [1 m+ u. @, z6 p1 M! D2 L; `
8.一个类如何覆盖默认的序列化机制?
" d6 p6 @: Y2 o% g: g7 D8 G) ^9 j5 t( z; o& B6 q& Q6 k
A.使用__shutdown和__startup方法
" |% Y1 M9 E3 l6 _, c( x2 YB.调用register_shutdown_function()函数2 w9 m$ e& K( i
C.使用__sleep()和__wakeup()方法4 j; P( m( l; E$ `; G
D.无法覆盖默认序列化机制
( ]7 b; W% V5 DE.使用ob_start()将类放入输出缓冲中9 |. h' R3 m8 u6 q
0 {9 j7 a8 ?. A' U* t
4 P0 s9 Z  _# s" Z9 ^0 D5 r
9.以下哪些面向对象的概念无法在PHP4中实现?/ _  b! i; ^5 D- }
; s2 b8 Q# t3 G7 g
@抽象类" X. T3 t4 L4 W
@Final类
+ H5 h1 W. y! A, C* s@Public、private、protected(PPP)方法" i+ C0 ^' I, Q5 m
@接口0 D% |- |) a) P: [% H9 l$ z
( s! Y( ~- x4 t* m9 {2 P
A.抽象类, ~. |% n3 s0 L  f- g+ J
B.PPP方法
3 T5 k# U5 p) gC.PPP方法和接口9 Y! X8 r$ B0 y5 }8 O- Y
D.以上所有都不可用
5 b* {0 G' O& ^2 N8 l- OE.以上所有都可用+ x2 d' R( j) |6 W4 S; O% w5 ]% E" A

# i; G/ {, N+ N' S- p: ]. U
4 z6 D. s, C! z, O; k10.如何在类的内部调用mymethod方法?
( P4 D$ t/ m/ n" ^  m3 d3 w# c( K9 Q( j" R! A
A.$self=>mymethod();% K! }2 T; _; K
B.$this->mymethod();. Z- ]+ |; M/ s) z, N$ V# P$ ?
C.$current->mymethod();/ t6 h' ?! Y; y5 T. z4 Q
D.$this::mymethod()4 V7 i( A4 U6 V9 V+ e  @8 N
E.以上都不对
5 C( i3 z8 S/ Y9 H4 G6 s" G+ ]. \* j3 }: Z: V8 N! a
6 \3 o# P  K7 C7 r/ c5 k! o) e/ L
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+ n4 h# Y. E$ R8 ^
B.Null
, h0 p# M0 z  Z* E4 UC.Empty
& R- Z1 m; j0 n9 w$ A; |0 q% s/ tD.什么都没有1 }& k/ Q& @; m3 D# \) \1 ]
E.一个错误
& Y% m$ h) F0 Q5 w" d# I6 Y$ X$ W. n% S0 b4 j9 J& \7 k0 t

; I, n0 H5 x4 q4 |0 N' a+ m# h; ~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- c- Y2 X( p! r4 j2 d
B.5) j8 F  C& I+ Y" s: E( ^
C.2
) w+ [9 a* ^* A7 J5 B% X1 g( q- t' JD.Null
9 v  F3 M+ ?7 T/ t4 s: ZE.什么都没有
9 }5 o- Q; l& m7 d2 k( u6 g% s' n" ?- r; B

: ~1 A' ^8 ?: a% K13.以下脚本输出什么?

  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.57 G% P: ~: f; j. p4 |, v9 g
B.10
, ~! X9 W- S& c/ }6 M" G. \  {C.什么都没有" R, Q9 ^$ ]) L& e7 u; @8 M* Z( Q
D.构造函数将报错
( m) i, U/ s1 E! UE.510
' T0 W: ^  e  }* p$ d5 D! j( d3 C- L2 D0 W# M2 \3 f: c- k/ ^

& V+ n- [. D3 T* M8 ]  B3 t14.考虑如下一段代码,执行时,$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函数必须返回一个值
( l* j+ E  S: u9 q6 x. c0 o0 \. [+ ~B.reduce_fraction函数必须接受一个整型值  {5 s! M( s$ e5 f' a+ H" B
C.gcd函数有问题- k% O7 i3 T; P4 A9 j
D.必须通过引用的方式传递$eight_tenths对象
+ ^% s6 a* t' B0 KE.对象的实例不能传递给方法以外的其他结构。$ ^" a. ^$ \, \' o7 \! H% ]

. {- |: K+ e- _+ ]# y0 \1 F/ N; R  \, M. ]
15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法0 e+ Y) I7 U8 }; ^
B.生成myclass的实例并调用mymethod方法
6 ]. V0 K* Z: f$ z% M3 b4 |/ ?C.产生一个语法错误6 J( e0 p. H. O3 T$ H% p5 u3 F
D.默认myclass类最后被创建出的实例并调用mymethod()
/ ~3 t+ A" x+ l8 \  M( x1 s& d, WE.调用名为myclass::mymethod()的函数
4 U9 G$ w) u9 f+ x) m
; p, C6 U1 y7 H  {# n+ u
1 Z# l3 k$ ^/ }8 Y# K' S+ G' _1 J; @) I7 L16.PHP中有静态类变量吗?( ?. K# T) w" ]2 O- o; f# }4 K

- f1 {- [" o3 y' }5 Z& kA.有5 y( w1 v- D$ }2 f" `. V
B.没有
  U2 ]8 {0 w0 T9 ?3 A/ C$ [* l% F6 p

! q" C# r3 d8 a2 |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. ~) Y3 J! G3 C' r
B.2$ Q8 |5 H$ k: f
C.一个错误,因为没有定义a::$myvar
& e/ S0 g1 C% P: nD.一个警告,因为没有定义a::$myvar# v; l" x; ^# h7 X
E.什么都没有
' R$ f' g6 [; X4 e6 ]! @5 W2 a; H: j2 R+ M

2 a3 [: W! X# T5 |3 l) b18.如何即时加载一个类?
5 g) a/ h- e: L6 b& Q2 _% X  @' g: M! w* }$ p
A.使用__autoload魔术函数
& s' M0 v% D8 g0 k$ L0 Z$ p9 |% CB.把它们定义为forward类
4 j' Z! J0 o6 [, X7 G% E) IC.实现一个特殊的错误处理手段
' n/ K0 O0 r" o; `+ Z$ i9 HD.不可能5 f; S0 k2 a/ E$ s' d, `& M/ J
E.用有条件限制的include来包含它们9 I) a9 B& P5 t* @! j

. E/ v3 j  G% o/ d8 O8 o# I# ]( |8 g/ B1 ~" ^% a. k! W+ {
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?7 U7 |! u) c: C& T
/ U: H( P( b6 \7 z/ b6 A3 S6 b
    答案:__________7 H5 a  Z. v9 ?' _% a- h

- }: T2 ?( Z4 U7 W* K% b
8 Q% Z: I: e& U& ~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
  h& F0 |  M' T0 Z' l. g$ u# f3 x8 Q7 [B.一个错误
: r# k/ M& F" ~: I6 sC.一个警告
% {) p+ ]* _: N. W* ND.什么都没有
  O- {6 z  [" k5 N( t- v( [/ _: ]' h0 l0 v% C5 ~

5 ?+ H8 t7 f' v3 P% v2 z& G' ~6 r; p5 U  A8 _2 K7 @
答案速查
* z+ f$ \; [/ n  A8 @: x& g1.类
+ N; ~1 k3 H" f% d' M; d2.BCD: [- N- f8 o# Q, d" N6 M& f
3.C$ l1 f: T  U: ^: l, \
4.C6 L3 L7 N2 f. E) p# \
5.A
0 v: L; h7 Y: G. k+ w. t6.C
% d2 ^9 S( l2 e+ Q7.C, \! a  N$ c' X
8.C
) k/ ~5 p8 Q  V1 c9.D+ \+ `" g. l  `+ S6 s; \+ s6 ~
10.B
7 ~; w" B' ~% g2 T$ W11.D
! M' P9 |4 U4 L& k) A12.B# \# a; k, j, |9 C
13.A/ T* ?" o+ O! k* P* R" v
14.D8 Y$ R! z  Y! I2 n& D  E* R4 p" P3 C
15.A
' N5 l+ ^" T; d+ y) I- `16.B! J2 e% H9 ?, ]( L$ @5 H
17.A9 t, U* d$ m) o, U+ _$ X8 Z
18.D
* M. {6 G9 A; p$ q9 o# R19.设计模式
4 [) A; k: V2 l6 N20.D
1 Z- ]7 X) `. B5 A6 g6 S+ v2 @* {# k

" I# s6 S9 j5 {7 U2 Y0 B4 l( A% S0 s7 l; [' ~' U6 m8 {
答案详解
1 _$ B: C% @1 Q0 s9 O" e% g1 b
3 D. O& F  {, }; f. @1.类是对象的蓝图(对象是类的实例)。: F4 Y4 T, \6 ~2 Z) i7 E

0 A$ F8 E. W, u3 c2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。
! {9 y  f5 Q/ i/ c
& T' c3 m9 o- x; K3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。, v3 ^' q0 K- p) f0 R7 N
# `9 f/ I+ N' I% d
4.单件模式可以限制一个类被实例化的次数。
" A7 z1 M! N: t3 H- V, c6 z7 H) L- ~: W7 F* }
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。4 }& z4 {* c7 \& O6 A
; D. b" j  w* K& `' v" d- g
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
- I0 i$ Q7 L( L
  x5 |$ `( L- e6 U1 }4 K' F# ?4 _7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
; \- e0 M0 J9 E* u6 T8 {
0 w( H2 H3 G4 q6 e" X5 M0 X. |% J8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。; e8 ~* S. h& v/ T

4 J5 `/ Z  m# J% a' J# }$ k9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
/ [# P% B) M& n4 E2 J
9 _# ]  D+ ~: X2 ]$ Z' ^10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。/ f  ~  F, E" V* j: S4 c
0 [: r  t& j* b1 M5 V
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
6 h8 ]4 ~( M7 v9 \6 r& y% w! v. f0 M) b( Z. V
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。# A6 y: _! u$ R( I& A
" n$ o' p. M5 Z
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
$ ^) c% h$ t' l2 ?
. v0 S; `6 a! L8 j14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
: t& @$ ?, k( U2 I回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:  ?( C+ S8 _1 C* J" X
    function reduce_fraction(&$fraction)
& P; Q' E1 o- n, C6 ?& {* v! l% ?( U# X答案是D。
* A2 U& _1 Z) [8 J2 L
5 p0 u( ?, E! _; {0 ?! R) U15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
% G3 f1 j+ W: H4 }7 S: V, o$ M' ~& {7 o, ]6 y0 N1 k- ]; w
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。- j, a' f! S  P+ N3 R1 a% o
( X2 a6 U- u4 `
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
& a3 t0 m: U* ^* p! W
. x* n* X* o' N3 B* R( L) l18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。6 T3 m  I0 i$ A2 |+ A
. M- N/ b: H) X& I! ^
19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
8 c4 H8 x, Z  h4 `" o6 m( S) o+ x$ ~% v$ L4 M7 b
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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