返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
, b7 z2 C) |/ |7 H& ?! s" NPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。/ R" Y, E* R  G* a/ F: e
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。, {; V& C7 R- \8 @; z
- T$ Q' G$ j  ~/ X* H
问题
# y! Z0 D* J3 ~  U5 \/ N: P5 \4 }7 j
1.对象的蓝图是什么?7 x6 m& a; d( S& }

" M, K( p& |* [答案:____________  \. m$ c4 d  G; {7 J! F! z
% T( |; P8 m) R; Q
% N5 F$ K# T# N
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.c0 l1 G$ j) ^& N6 g3 Q- O
B.b
5 @: T+ V# e- ]$ S' c. o/ v8 aC.a
- Z0 Z  ?' K% p) JD.d
" f' ^+ \/ W+ {E.e5 ~, r, S, o8 X0 j8 i# {" b; h
# N9 J. d9 n% a0 s4 W1 Z# C3 M
/ [8 L- C& u/ T. \
3.如何让类中的某些方法无法在类的外部被访问?& ^, Q- q5 N1 n7 m# U
3 v& l  @# h$ L2 C" w3 J
A.把类声明为private. }* K, r0 {) j* g' W2 p
B.把方法声明为private) l2 d/ v9 [9 E" `: {! P8 L
C.无法实现
! ?( z9 C1 S8 J: H7 ID.编写合适的重载方法(overloading method)0 P$ P' d" J) h: a! Z" G  v" H9 }4 K8 Z

5 r6 i# Q' k& D
8 ]- _! R6 l$ {' [& F* d+ I4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
9 r) s6 G- F- v
; q9 K* R7 E  m0 |: a1 d+ p$ K5 gA.MVC模式
/ n# O2 o) o% K# H2 A( gB.抽象工厂模式(Abstract factory)' d. y8 F1 ~+ t8 N( }
C.单件模式(Singleton)
0 x' L! A) }: s+ A3 AD.代理模式(Proxy): b, D5 v: D( x
E.状态模式(State)
  ?( \" z0 d0 a, o+ \; k% [1 F  X5 x3 ^0 A' M- ~9 Y
0 D% l: ?1 S' B& @$ z) u1 @
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
" I. k( V8 X8 V0 s: W7 u: w4 l" o- J5 `# g' K6 C6 r
A.1个
- f2 x, z3 W6 s; z* I7 n% W! J  z8 QB.2个
: A. w4 D* U2 k; l3 u8 TC.取决于系统资源/ O( x  Z% |" G- f2 v1 O
D.3个
* X; f6 V# b/ b/ d* UE.想要几个有几个" Z" \- _: A( n5 V' G, \/ G

) J' v4 I" @: m
" l& @( p, R' k9 u. e7 r4 P) n6.以下脚本近似的表示了一种在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.多重继承. d. n( b* a: Z# q8 i3 k
B.接口  h3 m7 t: {& G3 B' t
C.抽象方法
- O- S, \. z. ~) u- [/ J5 a& Q7 [. \' C  qD.Private方法
( \  a( g9 K% `; C4 ]: lE.函数重载(function overloading), e  G5 l7 f6 P: l$ i, o, t! ?
7 ]& w" s" P6 G9 i; y# y0 L
& Q& T+ P5 M! d; }! k; R
7.假设定义了一个testclass类,它的构造函数的函数名是什么?
3 q, z/ @6 n# X0 S0 `! p; e6 v6 @" |5 j
A.__construct+ {) z3 W  G) d& e( G- g) h
B.initialize
5 J7 q& m  M3 I: \, t* s0 TC.testclass- @6 P' p2 }4 L) J1 g
D.__testclass
: k( p, `. o' p% N$ G- ]( t8 V& ZE.只有PHP5才支持构造函数2 h9 s7 h& q% p: ~# f* }

# q0 e3 }; J1 U
" x; h4 X6 _! r: z) w7 L9 G) J8.一个类如何覆盖默认的序列化机制?
% j5 @* q- |2 d. |: c+ L* S9 ]0 e/ b
A.使用__shutdown和__startup方法7 [; u2 V; x& M* }
B.调用register_shutdown_function()函数$ z% b2 V. f* t6 l( g
C.使用__sleep()和__wakeup()方法8 N" Z" W: P  {3 W6 a0 U5 Q2 q
D.无法覆盖默认序列化机制
7 B; K0 u% z5 l9 X+ HE.使用ob_start()将类放入输出缓冲中6 p% v" [" }, Q4 H1 _* y

6 @: W3 Q- F* k7 G5 ]- A# q# r& ^% X) c2 U5 c8 Y
9.以下哪些面向对象的概念无法在PHP4中实现?
5 e2 _, |6 A0 ~* C$ E. t1 J
% Z* p3 w) g* T& d@抽象类
+ {" V" e" b- H- S* t* Y6 G8 h@Final类' o& k8 p, J9 D" k4 g
@Public、private、protected(PPP)方法' \' h7 k6 H% i! @1 k# F
@接口9 k& _, }( `) H& s: D

& B) [3 j& A9 K( bA.抽象类9 v/ ^2 P% ]% ~6 y4 h# W- R$ N& H
B.PPP方法
3 I& k% ^+ z' b. P  P6 vC.PPP方法和接口
' B: D4 F2 ~# |+ DD.以上所有都不可用
6 C, q3 `& @" `7 R7 W  k1 \  GE.以上所有都可用2 ~8 H& K$ k5 D' Y5 d
9 P) X  O" X" S' u0 K$ p
6 D& J& s7 R4 H* t2 c6 i
10.如何在类的内部调用mymethod方法?
, m& C* l5 T2 q5 g: j2 Q' b+ V6 C' Z
; s5 M  Y; }1 B, E9 r, yA.$self=>mymethod();
+ H3 ?" D! U! w9 o9 }; c( X5 {B.$this->mymethod();2 a$ g7 ]  i: z6 l  W7 Q: j
C.$current->mymethod();  ~. q8 |' _% |( B0 _4 b
D.$this::mymethod()
) D2 W9 n7 _  [; R6 V& rE.以上都不对
) Q# [7 Q8 t0 ]* S" l. `, L) _* n9 n" B
" g/ }; b+ z! m% G  t
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
8 ~# ?1 }& L, y" r! kB.Null
' Q' a) |" S3 A+ P4 h+ w& K, CC.Empty
6 T5 K3 a4 V: Q/ Y+ A, T+ HD.什么都没有8 \. ^- ~* I* V0 r3 {- Z1 V% m
E.一个错误8 ^- y0 N6 \- ~2 E: d6 Q+ P, g6 M

% E- ?5 {) V- E) x6 d
7 [5 i. x: S5 A1 H- N3 e  o12.以下脚本输出什么?

  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
+ I6 r: r8 L4 b* U0 K8 VB.5
' P: I6 Y- w1 D6 P; LC.2! R. W3 B: ]  D5 C' l3 Z
D.Null1 i* l+ ?# [6 y
E.什么都没有
$ q0 b& {' {8 b* Y
4 C9 i$ c3 A8 m3 Y" P5 [8 w/ S* O9 P" ~
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: @" d( ?( t, @- g0 C6 [
B.10
( U, |: A/ ]* H  Q7 x- JC.什么都没有0 E4 r1 b$ K7 [# ]
D.构造函数将报错
% p+ @* W) \  C* ~5 fE.5104 ?& f3 v. ]* R' a6 Z
3 d9 ?) ^7 M8 i/ G% c7 Z5 H) w
2 U, s  K/ X" j  p( ~+ Z
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函数必须返回一个值. x6 u4 G. z/ `% u7 Q8 R: f6 Z
B.reduce_fraction函数必须接受一个整型值
( S' O! E. g0 F4 R: `C.gcd函数有问题
" `5 J# E; J4 w% Y) ]5 K8 f7 y; ID.必须通过引用的方式传递$eight_tenths对象
$ {+ C' r0 K5 f) i% s& CE.对象的实例不能传递给方法以外的其他结构。& c% {+ k1 `( x% L0 v1 \0 x; x
! R4 Y  p4 G7 K5 u& }( j4 S

% V$ A: Q- y* j( T2 N3 A" ?15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法! y9 W6 S# s1 N6 U1 A+ T7 H
B.生成myclass的实例并调用mymethod方法
4 U3 U$ e% V0 n1 L5 k( \6 k3 YC.产生一个语法错误. s+ V8 M6 V- Q2 q% j! |
D.默认myclass类最后被创建出的实例并调用mymethod()$ d4 K) j3 C0 C7 k7 Q
E.调用名为myclass::mymethod()的函数3 Z4 W  z) k9 n( F+ ~" e" p& }

$ I( K5 `9 ?8 w% B+ L, u$ B% u, s+ K' H
16.PHP中有静态类变量吗?) k  G* I5 v  L+ T7 Y
( ?: }6 X2 d# U9 G/ I* w; \
A.有
! C2 q' K2 t8 SB.没有
% a) l, L, g; w6 T. y1 _; m: d1 |* i# `" g. P. x* v! k
9 a0 R) l0 [2 @
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
9 e5 V( s1 T# H" {4 D0 V- c& aB.2
, h/ g1 D5 V4 ^- E7 RC.一个错误,因为没有定义a::$myvar' y. x" [. k& ~3 d6 F& J' U* e% `6 J
D.一个警告,因为没有定义a::$myvar
6 T  o( ~9 s; L2 \/ h# r* |% f: GE.什么都没有8 r( ?* {- K) o7 H

" R6 j9 M3 a2 Q3 `: e/ R
; a( c' \1 G  ]- ^! B18.如何即时加载一个类?
: L: B( \# a0 U/ ]1 T, @4 l
& f( O# O/ E# q0 w5 y' f0 RA.使用__autoload魔术函数
8 w. _0 H! k6 L" G: D. M' zB.把它们定义为forward类
8 [6 Z/ B4 P6 y& Y/ h+ P- O' F! ]C.实现一个特殊的错误处理手段+ h! E9 a1 v$ V( m
D.不可能0 `7 u0 W' z! W9 U; d, \, t
E.用有条件限制的include来包含它们
! A/ P! c2 S8 O3 k* M6 h; O) [- X1 V/ u, f3 a+ u% H

2 `: S3 `  ]# X! L. p. [19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?8 ?4 S3 G; S0 P: q/ d2 g/ q
' g4 {% X% O' I( n4 [
    答案:__________
, q6 b  {2 {' A# I3 H5 d
/ X) S' w* w4 C2 X  S# m, W- k9 Q0 Z" c/ g$ c  i! ^8 ?" T9 q
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" e( u% e- `& G7 z
B.一个错误
0 T3 Y, J$ O& r& \& j- \- t' d- f" nC.一个警告, E) g/ h" V7 B; \( Z* U9 K, ~$ O
D.什么都没有
& W$ ?$ L0 `  P# V7 }) k# a" t/ H; y. e# A; ^% Z" V
! @5 j) ]1 M- H+ G$ w& _! x

# A$ S7 S% h/ D! I" X答案速查$ D8 V; R+ b# t8 c% O- T
1.类
  x7 }  }9 [9 d  Y; Z5 A* @2.BCD
7 \/ U( @5 g; r4 h3.C2 e) O/ u; {$ _7 m) m
4.C; O: v9 X) ^  i$ K& G" N6 ~
5.A$ b0 N( w; k) H3 L5 b3 g& m
6.C
; E9 C; ?$ H* }' o$ Z& u+ S9 g9 Z7.C- j- m+ I6 {8 ?# w
8.C
2 c( {9 S0 H  t0 t* ~! S9.D
/ s2 Q7 w* `$ q  O10.B
) ^) v5 |: n2 q3 Q* n2 a11.D
4 J& R1 V7 F! m2 [12.B; _% M5 x& s, b" Y  J& f9 ^: p# a
13.A
  U" V* d$ K. m, l- w14.D
  q2 \; b3 c0 ]/ I0 c8 x9 L. W15.A
7 S2 m! T+ E# u5 L16.B  H! j9 s1 Z& l" F7 o  F
17.A2 A  C  j+ Z$ c+ Z7 T. F. F! h
18.D( C9 _+ I; D: K5 ^0 K
19.设计模式
$ J. W* w* ^' E20.D
4 |: Q# I. \/ T0 \# D4 I- w6 ?) ?
/ @  D% `; T  b
( ]% c- y& i( q/ \, P0 O8 f  f
& x# I% i- y) O8 A0 }答案详解* r# }1 |1 p7 f2 }8 F) h6 \& g

. }/ f  V: ]* c3 x7 L1.类是对象的蓝图(对象是类的实例)。
, ]+ J$ O- T) x. p8 ?* o0 `% h5 ~  p2 P- T9 H
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。/ B* k$ n3 N* ~8 T9 Z, o" Y

2 w/ d& P& [$ r0 S, F+ G9 X5 V& b3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。3 j, }! e+ k) @; x- V
( s4 B& v' |, O" a
4.单件模式可以限制一个类被实例化的次数。
  Q* m5 T& G4 I1 J4 \" l! T3 y- ?  G3 k- M$ T' r
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。+ y, J) ^7 N& `; x5 Y# Z% z5 u. @
: P8 ~' |& [/ M$ v* v' d
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。6 q+ n( q+ G6 f# z6 {# b* J) x8 R

# i3 ?, g" G' k  ~7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
7 m0 }' i+ M+ L) L- \, [: h9 V; E& g8 E& k/ W
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。4 M. A- Y: g$ E' p: ?  p

8 {  V; f4 s0 m' j% M+ q$ y9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
0 ]8 b( f( B! g  w) H
" X# ]# a7 D$ u, I0 Q' C5 j6 g5 }10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。" R2 W$ y% v' B+ E+ l1 q- ~* _8 ^9 {

& K  s5 ]0 o/ g/ o11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。' _$ X& |- o6 H  B1 ]

7 ^! D# U; c5 Q. ^7 n! O12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
2 b! q7 N, @) P
7 {9 P* |9 A1 e( f13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
9 M* M! E/ x1 I. N' R+ K) k2 f6 Y
/ A: p: h# q+ Q! X5 S! ?14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。8 u4 o* h+ c& L1 y' t  O
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:; L* U% D, n9 O6 l" m1 ?
    function reduce_fraction(&$fraction)
( x5 t6 o# _" f) h% K$ I答案是D。
$ g6 D- g1 q( M* F/ |
# e3 _; U. i2 f2 g1 G15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
; t# `6 W  Y4 b" M2 b9 h# c, I* {
8 @  R! M- m* l; d16.没有。PHP4只允许声明静态函数变量,没有静态类变量。. z7 s+ u3 u6 q. d" q

1 _+ U; w! u/ Z6 [17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。; U9 \$ p+ @1 z) B
8 u: E' \7 j# i$ r8 [% f9 ]
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。4 V8 p- R$ V, q. ~3 D, W

3 J8 C0 J* D6 s* V# c* [: C$ v1 @19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。$ V7 U4 c9 l8 T3 Z

0 v  w- m& f' V% [+ s20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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