返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。# D7 D( Q! K9 T& _0 |
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
* k! m" {; l" }- E! Y& g4 i, N本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
( f) p- Z/ V; a+ s* q- {; g+ @; ]) T7 B4 `! Z0 G' F; w
问题$ w/ |) D' w9 R4 X/ n- R
# ~7 _. w1 L6 E$ E2 Z
1.对象的蓝图是什么?
$ N: K2 }% y# V( |7 A/ L' U1 ?' P8 _0 p% M, s: M: p8 w$ _, \
答案:____________
/ @9 {, c: E& h
' o2 |0 t  t0 r# Z
, r1 U! G+ t/ ~; U" @) s2.以下代码执行后,数组$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.c0 k, O& h" B3 k5 `. D% _
B.b9 G# s4 ~/ r- }% `% ?
C.a
; E& U" C. N3 @% iD.d
6 F. k. X; [' }/ \9 F5 H& ZE.e; R. T' z4 D8 n7 J
0 ^$ `4 U' _0 o* E/ }
) F# n. H! P  [  M8 j$ {: z" d! Z
3.如何让类中的某些方法无法在类的外部被访问?( S$ k9 F( ^. v

8 N  U8 E" {( m( n& A8 E# w5 bA.把类声明为private
" s0 U! T. {% e4 PB.把方法声明为private
' ?& L+ e+ a+ ?# H! W1 H* i$ EC.无法实现( P1 c+ A" c; u4 _; i) v$ h
D.编写合适的重载方法(overloading method)- C7 W/ w$ C' e! I5 p

* S- F4 O8 t1 g/ t" j2 ?' e! f# i' J5 C. e. |" |$ k
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
4 x; d! X9 ]) |# O6 I
5 _3 ^4 v8 U: V( X: Z- U/ U5 W, p2 `A.MVC模式4 m7 ?: [: D* ~2 Y- B/ }% p
B.抽象工厂模式(Abstract factory)6 q  `1 J2 ~6 M3 |
C.单件模式(Singleton)9 o: B% ~- p) W% s7 y3 ?% Q3 C
D.代理模式(Proxy)
/ d- A" _3 z5 `3 ~- YE.状态模式(State)
4 K" F3 V5 m! j* k% P& N4 \2 ?- K- |0 i$ f; k. o& R
4 {# E6 ]1 g) u5 u
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
, I/ X% M# z( Y1 G1 t4 i( D/ z( d' q- r' \
A.1个
( P4 \% {1 U" ~& cB.2个/ E3 w2 V$ x. w6 c$ h" w) @
C.取决于系统资源% m5 \# D# e' ]' {
D.3个
( ], q( M0 ]9 a5 h& G. aE.想要几个有几个
$ f* v4 e' v: `- I' h
3 F& Y4 J7 [6 Q
. E3 D: x9 Q8 K" K6.以下脚本近似的表示了一种在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.多重继承
# J3 |8 ?" U  p3 _+ o9 K! z) aB.接口8 k- s' n# \" O" |% v3 z' h* [
C.抽象方法
$ n4 g' I+ |7 `. J( g- S) o! o9 PD.Private方法
$ f. I0 a, i3 A1 `# ]0 \E.函数重载(function overloading)
* T+ ^9 B- V5 r/ C. j/ k
7 j9 u9 N6 X% G5 d, D5 h% S
7 z0 I! E8 t+ ]& f7.假设定义了一个testclass类,它的构造函数的函数名是什么?" G0 f$ s+ g! a: k% o, E4 R
+ F  t0 m7 ]! k* K" u" v% G
A.__construct
- X0 v& U, D& o- v9 ~B.initialize7 G( M0 d; U4 e3 m
C.testclass% f2 X. `6 W1 Z8 E( J" c% ~7 y/ _: b
D.__testclass1 @# O' N" {1 X, c8 m! `
E.只有PHP5才支持构造函数
/ @' }' G; e8 I9 `0 E  R. ]7 F: N: Z6 D2 J
( s3 j" T$ D, {
8.一个类如何覆盖默认的序列化机制?
" n4 W1 g; l9 c  x
, W$ D, `% x6 ]- eA.使用__shutdown和__startup方法
/ p) B3 i9 _, D2 I" E" u9 YB.调用register_shutdown_function()函数
" C9 k" `1 N. O! u2 K( r( ^C.使用__sleep()和__wakeup()方法
9 F( {. k9 r  ?8 j/ tD.无法覆盖默认序列化机制
$ T/ K: \  I0 o: w/ O) q9 y& s* d1 CE.使用ob_start()将类放入输出缓冲中
. G4 `* f5 u% V$ N! J5 s# M. t7 X7 O  H6 {0 l" W8 T
% i7 ]5 z4 L( t1 @( N) V
9.以下哪些面向对象的概念无法在PHP4中实现?
3 D1 W5 h. a/ a4 f, z0 t- V  O0 \! M" T) n
@抽象类" b- z1 n( J$ n7 b. ]# a
@Final类4 Q& ], l: F0 n* [  P" [
@Public、private、protected(PPP)方法3 i+ U! }6 H" }
@接口0 l/ l* T% e) H

# [0 S, m" K* HA.抽象类; {- |) ]6 ]0 q2 w
B.PPP方法' K2 k( u7 ^3 t
C.PPP方法和接口
4 J. F( ]7 r, s' }- Y' ~D.以上所有都不可用
1 b  ~/ h5 Q% w% A+ b0 LE.以上所有都可用3 k  @& i" F; j* v! n$ \9 E

, e. ^9 v/ l& Y1 q/ X$ n* I) c+ X# y
10.如何在类的内部调用mymethod方法?
. U* H/ ]1 ], c1 m/ \% D4 I4 P' d" M# B! d
A.$self=>mymethod();
  N; {- ~6 x9 ~4 ~, nB.$this->mymethod();4 ~& o& d: e; q  V- L& V. J
C.$current->mymethod();8 }1 O' p& l7 ?4 G/ X6 V* q
D.$this::mymethod()& E# U6 ^6 m9 Y  c: t8 X, i
E.以上都不对6 D* L' a# X: w% m

* W3 H4 i, U4 {% @1 M0 d$ u' Y4 O6 v# E1 O1 e/ c# n
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
+ b1 P1 s! r) T' RB.Null( v' \9 l# [9 N* }4 n
C.Empty( F3 o  y) K+ H) ]
D.什么都没有! I; A% t; a2 s
E.一个错误1 ]( n# _3 v+ i, }# D' ~

/ w* K# f, M$ p, e! p6 K4 T8 T; }7 K4 f" P9 S9 Q3 l
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
% }+ P. _$ [( _1 k; GB.5
' |  C6 m" w, p& A2 y: y7 T, |C.2
$ A5 K0 |9 }7 m, Y7 ]D.Null
/ ^8 X$ v: G$ B, m) b5 P2 T0 lE.什么都没有9 R% j  d0 A! E0 \& b

/ B0 l' O( _) y; P2 r9 |  u* l2 \8 L8 A- I$ U5 L* Z2 Y
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
; R1 @9 h4 I- d& j& vB.10, [) B" u& B, t( _# w' ?$ I" O
C.什么都没有
( Y$ r, i4 ]6 z, i6 D: q3 BD.构造函数将报错' ~6 ~0 Y1 }& x" V
E.510$ R5 }5 m& y1 m5 g

: \6 L2 @9 F) `- A% q, l0 W; @! \* M- }/ _6 i. ?; s
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函数必须返回一个值! Q2 e. e- T  Q* C7 {! P
B.reduce_fraction函数必须接受一个整型值* J* w- O/ y" s# z" A: z
C.gcd函数有问题
$ d1 l+ U1 x- FD.必须通过引用的方式传递$eight_tenths对象$ G6 @6 C4 `" p, J! D
E.对象的实例不能传递给方法以外的其他结构。3 C. x8 F+ S0 P* D. \

& p& Z! J9 {# P/ I3 K. A9 s: l9 X5 X  \7 Y& @3 C$ t
15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法- z! S( n, U2 H8 D0 o% _
B.生成myclass的实例并调用mymethod方法, }  ?7 e( H3 y! n
C.产生一个语法错误
: Z; G' Y. x. `1 j# \: ], Y! {* ND.默认myclass类最后被创建出的实例并调用mymethod()
+ m5 A3 o4 l  |, Z( J/ ]# T( DE.调用名为myclass::mymethod()的函数9 r+ U9 g) a7 h( E0 e* S
; r+ _; ?* Z8 B( _7 V8 K
$ A, ?7 L6 K( n
16.PHP中有静态类变量吗?7 K, c5 T' z2 ~" H, Z
$ u& {/ L9 e% r8 _4 d6 d0 K
A.有
% L8 [. j" p% M0 f* v3 e2 r6 m! x  pB.没有
/ N4 B. ?, K9 ^7 k. _& d* [& ]. V

3 W! B3 _9 z( v  D5 }3 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.13 }& B2 I  K! {: d
B.2* r! j3 g2 t* u# B
C.一个错误,因为没有定义a::$myvar+ K# p9 E( M# [* i' N
D.一个警告,因为没有定义a::$myvar& A4 H* T7 C: B7 Y+ X
E.什么都没有
1 i! L- X  v. T+ C5 \
' k& L( r3 q1 f
+ D$ A. u/ ^0 v1 S# j; t% R18.如何即时加载一个类?
! F# x5 \2 Q. q. v  h. {  z
& \$ Z- {6 h- Y* LA.使用__autoload魔术函数
- p3 [- o! \; b+ j( x6 j0 J" s. qB.把它们定义为forward类6 I+ C3 u  r8 _+ D
C.实现一个特殊的错误处理手段
' M7 C  j' C3 g. sD.不可能7 H3 T. b* t0 Q1 ^" i" E7 b* t, P
E.用有条件限制的include来包含它们4 Y6 q+ x+ w) m% b- Y) |8 D" D0 }# b

4 L4 f8 P' i4 S- N, i
9 w+ g* ~' L2 Y0 Y0 i5 t5 p19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
' V! u& d3 O. p" M+ V, Q% t# t+ `" T+ L
    答案:__________
6 [) o- ]* @: k& ~9 @& I8 M$ D3 a# O7 G% W

8 G3 P! u5 ^$ B# G# h5 N# f% @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. f2 S3 l* g# B/ [5 ]) q
B.一个错误
  E: K. j9 V* q! }8 R$ JC.一个警告
# ^1 y9 y% J7 ]D.什么都没有7 D5 K4 H7 m8 e% c1 w; c* R

6 P( Q5 S0 Z+ f- m! |! i; R8 w3 O' z7 k
0 _. }) a, c: I* l' W/ f) A/ t' {& v
答案速查
3 `& f6 H. h; |+ s( Q1.类
3 q/ i3 ~% p2 k2.BCD
1 v6 O2 P9 _1 m$ ]( b8 Q6 z9 ]3.C# a4 k" s( G8 h: C
4.C
* z( J4 @8 h1 V: i" `5.A
" r. S4 m2 }5 ~4 O6.C0 ]& Q; O9 D; h+ K2 T9 b
7.C
& A$ C- a4 C/ {8.C
) F# r! ]2 B+ `5 W9 r9.D
6 f. O. Z+ N* s10.B/ m4 a6 ~" I" |& G5 {! E1 w1 x
11.D
2 {1 ]" L) L! G: L- R/ d8 i12.B5 t) }3 a7 d* T
13.A: \' R  O0 L3 F" @
14.D1 B" C- M1 H& F1 r. @+ q' \
15.A( s6 T/ g; \  m6 Z. ^- A4 `1 ~
16.B0 U8 ^% X( M5 f# M, e7 d
17.A
# O+ {; }9 S! r. T18.D. l) `5 Z; d4 V  l7 f. x
19.设计模式
  a1 ~5 [, {- p) n) |" g/ N20.D/ c  R, ]7 Y! h- s7 A; M5 G; y, D

0 a8 n* a! [! c3 S/ H, w4 x: E  h( ?: V# j

6 G8 Q" `8 o6 F答案详解$ G" O0 ~2 Y: H7 D9 D6 U

6 |2 E; _8 O* A& ]3 z, c  {/ ~1.类是对象的蓝图(对象是类的实例)。
8 d' E9 g, ^  z- B% \* l3 V- p% k, u8 P9 C
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。
1 x' d5 k% Q* f" o  a9 `. y7 o4 U7 ~' X1 Q/ u
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。! D( W- h* Q$ h1 M" o$ w
$ G1 G6 E, S  t: s& H5 ~9 \
4.单件模式可以限制一个类被实例化的次数。3 N% F# U" ?6 i6 J0 `' ]

7 N" J6 M" G0 U4 e5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。
- p" S7 B! i+ f+ w) G. \1 \7 R
% Z1 X  v+ q9 u: j5 Q5 k6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
( I  P/ [* O5 Y1 X& O% R! _* o% y) `. M3 D
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
5 V5 y5 V( V. r2 N: l; p" @9 q! o. }/ V! J
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
# j) q( c7 D0 `9 L  g9 k+ X, I2 v. F+ }% M+ k( A
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。( a1 ]6 K0 u4 k" E- s/ e
) ~  E( L6 m! o4 B7 G, h
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
& ?, m6 f+ ]% c  A
( g( O5 u, B4 K' }7 ~, J11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。  _. t$ S: h! z+ N
! @5 t, N2 z6 }2 s! q4 P; C/ p9 {
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
! R6 _9 l, e2 \% X: `) r; y3 H9 w* Q4 o8 v, t5 n6 r
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
$ J% Q, s& j/ ~6 H( s! L7 c: n& M1 ]) Z
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
3 |% U8 s2 M1 E6 {4 F# |回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:. o2 b: Z  Z5 ?
    function reduce_fraction(&$fraction)# h" _. E) _  n" U$ g3 D: X. R1 T2 p
答案是D。2 m) k1 X1 H/ Z1 a

- T. W- z7 k1 I8 Q# ^15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。0 m, V4 {2 F! \
8 t* g# h6 V2 t; i: N0 |% w
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。% b5 ?+ S/ P) E; t" k: D; \4 x6 x3 V
) @$ V$ M2 c  [$ @
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
' R* e5 l  k2 i$ g  ~* B, c" \  l; ]) k* V' w) b/ F( T- C4 \
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。' c2 T& ~( g* s. J) v, B

2 V$ m. F5 z; C0 }19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
  X) o5 D- s6 b) G; W6 S
9 I5 M0 o& O/ T2 g# `20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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