返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
) x4 N$ a) ~% [% S2 APHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
4 K5 }: O* Q7 V8 x+ H# W本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
7 F  q0 O! f& \' b3 q& D+ N
6 s0 U- q$ [/ T, a问题
& @. }* V; P* S. ]; d) g4 b  U* I! U
1.对象的蓝图是什么?7 z1 h6 ]% u* h8 [, b* |7 ~- W

/ j3 _' M% \4 j. I% n答案:____________5 s' K% d8 b) j# w

* ~. n# E% F( \7 E0 k( H% F* R5 w9 ]+ K
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
& s2 _. E" Y  }* h2 AB.b3 O' y" p  e7 n8 P8 n( Q; y
C.a
: c; X# p* e4 @% ^( a" F) AD.d
/ R' {, V+ u9 h5 _E.e# w" {- c/ |1 u1 m: y3 `

1 U# Z0 P) C4 y9 r) d
$ ?' v& u8 D" o7 ?) k3.如何让类中的某些方法无法在类的外部被访问?
$ p3 o1 T% [; Z5 g. P- z
& m& Z/ Q) \) M2 R; jA.把类声明为private* H+ M5 H* C5 n$ h
B.把方法声明为private
5 X& @2 T8 X* M/ BC.无法实现; e  E% U9 S1 h3 j* S' ^* \
D.编写合适的重载方法(overloading method)) t0 c& p5 q; E7 l/ H

) [) H% C* u  z( t9 S  c" i1 Q0 ^& i
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
% _+ k+ C  b. {6 ~, y) l# B& B3 v! C! M* V0 `
A.MVC模式
! r* ~  t# a7 M* ]5 h8 hB.抽象工厂模式(Abstract factory)
: D; C8 c: d( a) l# m) K! Y% WC.单件模式(Singleton)2 k# F- z6 I1 |4 W2 k9 F
D.代理模式(Proxy)
$ o6 l2 b- y7 jE.状态模式(State)
% {  ?  C# c3 O7 j0 Y3 Z# `6 b' I# c1 V. M
% ^. Q& E( J5 o) j1 M0 L$ Z' |& i
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?+ U6 W9 m" E. G, ^& w
* }$ ]! z# M! i" V
A.1个$ p+ ?* h- `6 W! q9 n) s
B.2个
3 ~- @3 _% U4 R& U, T: l* H, G) _- bC.取决于系统资源
, J& N4 ^2 ^. ^- Q: dD.3个
: m/ }" a2 ?: Z' _+ IE.想要几个有几个/ i5 N9 I% J: |8 V5 E

! f: `3 a0 B3 h: q' A/ v2 {; V+ \
  R3 X% h* ]# Z: N# `9 ?( z7 o' x6.以下脚本近似的表示了一种在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.多重继承; V0 g9 ]" Z: Z' v+ U
B.接口
0 a5 [/ E- c  M' n, u! cC.抽象方法2 ^. [1 C, g# D0 V1 o
D.Private方法
7 g5 M5 J, a' H9 M7 ~# Q% V: HE.函数重载(function overloading)
$ F% p- T& p3 l% ^% q9 b( X4 |$ v2 p& \

$ ]! H2 g# y6 ^% E7.假设定义了一个testclass类,它的构造函数的函数名是什么?+ S% l5 p7 b2 s( |$ ]2 o* k
# h. n2 n2 a: x* v
A.__construct% ^  `4 U0 o6 C3 Z! ?+ a
B.initialize
6 _5 t, x6 x- ^0 {C.testclass; s# Z& f  {3 |
D.__testclass
0 M& J! ^8 j  Q( i4 F$ pE.只有PHP5才支持构造函数
$ N' S2 `" ^/ u6 `/ z
( F1 b; c0 l7 M0 l- i% Z/ i5 S$ q1 U1 g# L2 ]; C- m
8.一个类如何覆盖默认的序列化机制?
" m) ~" x7 ^: d7 B0 {# }2 @% e0 D) P- j" n" L7 S
A.使用__shutdown和__startup方法! u: `$ I6 i8 v2 _7 v0 |
B.调用register_shutdown_function()函数
: v. F7 X' E* J$ D  I% @C.使用__sleep()和__wakeup()方法
8 I( A* E% Q& {( \7 E! y' lD.无法覆盖默认序列化机制
" ?9 T. h1 U3 X9 d  c' m- HE.使用ob_start()将类放入输出缓冲中5 c. M5 B3 ~: }. \
% C' _9 Y" ~/ P* b7 I: l; E. b6 W

! \8 W# k1 ]& J3 ?6 t/ g9.以下哪些面向对象的概念无法在PHP4中实现?$ ?* P. X+ E& q4 y- K) `

$ u, p) Z, |+ k  @@抽象类& W3 F$ T; K& S2 h3 G6 W! `
@Final类: m5 K! E  o5 w8 c  N# U
@Public、private、protected(PPP)方法
$ t. G; N3 H9 u3 H7 z3 s5 I9 u@接口8 y! |" I  b- Z0 d5 j% R0 b1 a; O
% L6 t$ |8 Y# P  ]7 z' Z, z7 i4 M
A.抽象类% B  _0 Q7 c. o& p" z; J
B.PPP方法1 u. Q9 l: v2 d& b5 m5 B1 h% h- J
C.PPP方法和接口
; l$ C# k" H* U- n8 QD.以上所有都不可用& p4 p( H& c0 a$ b
E.以上所有都可用* r3 r" w0 s* d

6 o. U7 }5 ~# q+ L& J9 y( h' d: v* K" Q5 W  Y6 @' O" Q) ~  m
10.如何在类的内部调用mymethod方法?
; N4 n/ Q+ N# X2 X
9 @3 O: S- o; j, g3 c! cA.$self=>mymethod();
  T) F- J# b. v- B) xB.$this->mymethod();4 E" v$ g0 X- m0 I/ f
C.$current->mymethod();+ a5 U4 L7 a, L5 F+ d6 X: E9 f
D.$this::mymethod()- e2 l5 E! K( c! ?5 z3 U3 t
E.以上都不对7 v# Y2 ]5 j) V: H0 d2 n+ x
8 C) v3 H* _3 V( ^4 j; `

) D+ f; x5 s5 S# L" c0 P4 r- 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
5 U& I$ r& _; X. QB.Null* O: @  G! R# `! r
C.Empty
7 V) h$ M9 O( T- S0 W) n5 V; ~D.什么都没有* g$ U$ m0 R( J% c7 c) l
E.一个错误7 ^9 o) o3 @& {/ y: R3 |+ j
9 X1 {. E8 p  G4 k# Z' Z' s3 I0 d

! Q& ~! ~5 A4 K12.以下脚本输出什么?

  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, I5 N  Y1 C4 A( x4 {* O! y5 }7 U
B.5
5 @4 m0 B) m/ Z- G2 q8 B$ U% MC.23 m: `9 j0 ]: o) a" V  R! X, O
D.Null
* F5 d, e! y# u( g  y$ CE.什么都没有
0 E" x2 T( f- ~' N9 f& k- \( {: z% ~+ X8 W
4 ?  Y6 W2 N% U7 _
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
5 k5 T$ H% ~3 w2 H6 oB.10
- {4 X/ ]* y  }1 g$ ?% UC.什么都没有
* w" R8 g$ x" l- n4 W! |$ G; |- ^D.构造函数将报错
& v6 c1 ~3 G; t0 z; l0 g; i+ j. AE.510
) M7 z' k8 w9 j' P( b: ^6 z( P2 L( ]0 h# G/ U

  G8 y# X$ o8 \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! L7 H' X: y, E, EB.reduce_fraction函数必须接受一个整型值4 j4 c% z! w% I$ }3 Z3 q
C.gcd函数有问题
+ ^. L- m% s8 o3 H! [0 ]+ dD.必须通过引用的方式传递$eight_tenths对象3 A8 B+ ~! L# H. r
E.对象的实例不能传递给方法以外的其他结构。+ R+ r# h( q  |, b; Q; ], b; G' K; M

3 \5 U6 p6 J- z# h
. X1 H" j- Z7 H) i) o15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法; y( @$ m0 I$ T& l- I' m( {1 f
B.生成myclass的实例并调用mymethod方法/ T( F* d& A+ c; ]' H% u, N
C.产生一个语法错误
. g' P& h* F: sD.默认myclass类最后被创建出的实例并调用mymethod(): Y. {5 \2 y( O' X1 j
E.调用名为myclass::mymethod()的函数
  _4 N& n. P( h& q, p5 s' ^) Q' ~. O4 E: ]

4 x5 g1 i5 Q4 x" d2 b) _* b16.PHP中有静态类变量吗?" U+ C" u! k8 Q( [( I1 o+ h# Q

  [  i2 D8 y8 m, YA.有
' y$ b8 y. ~1 a2 B7 n3 y8 [5 f8 {B.没有; s3 _0 |, A: l+ @) K
5 y; b. q! n' _. U
7 n% T4 O! e) g% ]/ I# t
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.13 Y% {4 v/ U) r5 }6 m) f8 c
B.26 L3 N- |$ }1 ?, ~( ]4 `7 @0 m( R
C.一个错误,因为没有定义a::$myvar
* k, {$ p' |) k0 \% I7 ~+ VD.一个警告,因为没有定义a::$myvar' f/ {  Q2 V8 l
E.什么都没有
4 l/ L3 F: w6 i: s  x, ]. m: n2 g' ?& K3 f: o

% ~* w( @$ J6 q) l% j* x18.如何即时加载一个类?, h/ O: b9 d: C% M& g; j
8 `+ y* u; U1 O
A.使用__autoload魔术函数
# R' {& D# T. WB.把它们定义为forward类' N  _0 k( _/ I  ?+ J1 ]
C.实现一个特殊的错误处理手段7 D5 {" n! ^) k" j
D.不可能- d2 L" q' F6 O
E.用有条件限制的include来包含它们
) v6 B2 I* @( Z. P! p
1 p. b/ N* x' G/ r' K2 Y) x# o6 \5 R' h6 M7 ~2 R) o
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
4 s" |5 p- v* N5 E% r$ U
( |- _7 f8 w( x    答案:__________, E" a. ]0 H$ {+ U6 B7 K9 U
3 B5 J; i0 a. F
9 B  O- Q* ^4 W6 ]
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
( o; R* ~9 N5 m. S& r* UB.一个错误
# i  Z+ ?$ J) s: {% oC.一个警告
, e) B' p* n' W: bD.什么都没有
: O/ \6 d  m* s
# V+ M4 s4 C$ S3 {- E( r, ?) d
8 V' e1 ^- z( M: ~% P- \( U1 e" l0 [# G* d  U! k0 p
答案速查
* f* C3 f' [7 }3 M% l' G% t7 \1.类2 n2 X' x2 J3 t* o
2.BCD
, B" m4 W* q; M, O) \3.C' Y! e( Y$ t" I- ^1 z4 l
4.C1 ]( Z2 \8 O0 T  }0 R
5.A
& ]( F4 h  b9 U$ z2 k3 Z4 P6.C
. S% y; f- c0 [2 a& h* Q0 R6 y7.C4 y, q2 [& W7 Q. g# O4 y
8.C( f, G+ c( m5 t" B  v( c  S
9.D+ I1 y& ?6 A# y% I- q
10.B
( ?  a- x0 N) y  u9 ?: l11.D6 Z* g2 y. X) e* G
12.B6 f& i& |. Q! _6 ]$ l
13.A
% c# ?) t! R% R5 T: R5 e14.D
6 g% A) P& x9 d7 O15.A, ^) u0 y6 j2 [" a5 W
16.B
- \! f3 A+ m3 M5 x17.A
7 `& H" h# a! I# ~5 Z18.D
) k' M( P' T! \19.设计模式5 C  K3 a1 Y0 A8 W
20.D  C8 H# o1 G# k& @! G

8 X5 m; V4 ]7 I) c. O& j7 M7 A6 l$ z- t
, `' r$ X, X  ^; L9 o$ ]
答案详解
# C3 a/ T& I* g/ T' [1 s% x* i4 y7 ]. z
1.类是对象的蓝图(对象是类的实例)。; Q7 A$ g) w7 X, B0 u7 G- [" s
& |. [% }/ E: d7 p
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。/ i3 r# d9 N: @0 Q; W% r" l
2 R% ~* s% }, A- r+ s1 c; O5 j& r
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。1 B' Q* e- [4 F$ ?' S* s

3 Q/ `1 g4 `& j* `1 B  t5 C( r4.单件模式可以限制一个类被实例化的次数。
% ]! Y9 Z% B  i9 p( ]1 l6 g: J9 z! g0 @; P6 g
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。) n5 |0 P9 f+ \# W$ M9 ^
. u) T7 \8 O2 ?; p
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。* Y  ~8 k2 l0 ~- [  W5 p1 m( I
1 q" d" J. i4 F# f
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。- J/ p3 T! L5 j, {

" U) k3 e0 [* q0 l+ l- ^% D8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
: [) }; M0 C8 o( E  E; R" d1 K* n3 |- p3 j# j: j3 b
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。( s9 i' t! o' R$ ~4 c
9 p4 n6 w% p! J5 q# X. k" C
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。# d  ^6 @. h2 U+ z9 @: T0 q

! H/ C' F& X' l+ i0 h11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。6 P. T/ Z1 Z- s8 M% N) X% P
" a- y" J# d. Q* K2 b
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。3 S- A0 s: H3 N

3 t3 e4 G2 T! B* k' V; F8 B+ ^13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
( T- c9 R, X  B$ O* {7 m" ~
! j' D7 S' W; m- a9 S14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。  o* _" Y1 N6 q! o" w
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
+ I+ |: i/ W2 \    function reduce_fraction(&$fraction)
1 T: ?; i+ \/ \- _* ^; W# Y答案是D。
/ S( i: R2 T( L  v% n1 W4 I1 N" y6 G% b/ {" M
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。/ C# f6 K  ~2 q5 _( N) h6 q

+ F  k: j( b  F! T3 j  k+ s16.没有。PHP4只允许声明静态函数变量,没有静态类变量。- U% x' h/ i; B8 E( p' l
( U+ B0 q5 W4 S6 `: V7 Z! E' L
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
- s2 @+ P6 r  _4 t
) \; {8 H3 c7 U6 [/ O18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
: z& t8 u! V: a6 I1 q
( _' O! q) R9 c19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
! ~( k; o$ L  F3 m
* `' V3 V; }. v' L) B3 D; u20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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