返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。0 F2 v6 R) H& L& b* l; D: b- K3 N7 }
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。$ \; q7 a" x$ H1 [
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。' m2 x- J- B8 r6 F

. G3 M1 n% H7 k9 y& Y3 J问题
% W' k! j# D' M" A% U( }, {3 @+ P7 p6 Q: \
1.对象的蓝图是什么?
. m: c" l# C* v! b3 M& t0 }3 ?' R
7 |/ R" Q& `& O: x% n( n答案:____________
/ d/ }& \4 b' E1 ]- n- e  ]+ q0 l: S- _  c
/ j# @5 j/ w, G8 A- j: l
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
: L% m2 d7 y% [# C& J& DB.b. Y* B, E, S; B
C.a
% t! J7 U! J- dD.d2 R; X- q# _: o6 U+ P  v- z" M
E.e" c7 c4 f0 u/ f2 ]9 X% W  J
. |5 P) m: J: b, F2 E% L
2 |! Z7 v$ j3 l  _
3.如何让类中的某些方法无法在类的外部被访问?6 t0 i1 b, ~* T, d
8 K5 O! r5 n; H
A.把类声明为private' U) r6 [' X0 x' I& [
B.把方法声明为private# c, ~' f- ^. @; J+ W* i& |$ Z- \6 X
C.无法实现
  @. u/ L4 d+ E9 j; S, ED.编写合适的重载方法(overloading method)
9 \  c" a0 D, O7 R. i2 r! {9 _' B* Z( b0 h# ?  ~7 s1 l# U( z
; @0 v1 w+ T" p0 N1 ?  x
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
6 k4 _# \" P. ]
& a& A& X4 R! @- P: d+ ~$ zA.MVC模式( z* J2 ^4 R/ `$ z4 I
B.抽象工厂模式(Abstract factory)
9 Y$ p. ~- K; x% RC.单件模式(Singleton)
& N$ z7 l5 @0 k6 z, C& dD.代理模式(Proxy)
+ c3 r# Y$ T, }" A- ^E.状态模式(State)2 S( B4 A6 P* u2 _, P. s8 u
  w4 p& P. ^" M  g/ }& ^
0 M$ V0 V" z7 Y- K
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
8 ]/ `# Z* C+ i! n4 k2 E4 X( ?! M8 F' w5 _* J
A.1个
. d/ h: k6 ]6 R6 \1 sB.2个
) s: f$ T6 w0 h( DC.取决于系统资源7 u# {1 s4 s" ~; h0 _+ H; s- \/ M
D.3个
- Q* c, s6 B; J. Q% ^+ O, v& qE.想要几个有几个
7 J4 O5 Z# V+ _2 v* ~6 x7 j0 h7 y( E# o- Z" C$ L. q0 i

8 \6 M0 I6 p* E, [5 l$ l6.以下脚本近似的表示了一种在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.多重继承- i3 G6 ^. e( n, ^
B.接口
# l8 D$ k; U% X, m" \0 c+ ]C.抽象方法
# a% [; z/ w& A* @3 jD.Private方法# ?) F% I/ D! o7 }
E.函数重载(function overloading)
. t, @+ X, E4 f# N7 v; A7 e& [# G9 H9 J: C
0 ^& k8 ?! q' J
7.假设定义了一个testclass类,它的构造函数的函数名是什么?
( k( i+ D& s" j+ _; |9 U. j4 H9 ^5 F+ g
A.__construct& r2 D$ Z6 f/ E* e! o9 L. `: O
B.initialize. }1 g) \  U& D% K
C.testclass0 m4 M+ F: H6 V3 r7 A
D.__testclass
; }9 \) d! w* n% q% g1 S$ PE.只有PHP5才支持构造函数% C9 }4 o  O  ]0 c

* U& b$ ^4 a, y4 {; s) \/ K3 ^
  v/ Q; h+ u5 }- s( L- e! I- |8.一个类如何覆盖默认的序列化机制?
8 w" V' y7 a! t8 R- B. ?
) B/ \+ O* F& g8 YA.使用__shutdown和__startup方法3 ^* T! j# U# R. v1 }
B.调用register_shutdown_function()函数# y" j- ^" l# o; P7 z9 _" B
C.使用__sleep()和__wakeup()方法* V7 Z$ R% X6 f+ }$ C# U+ L
D.无法覆盖默认序列化机制
( G0 {; {( m/ `E.使用ob_start()将类放入输出缓冲中, Z* J' {5 f" H$ v
5 J2 Q1 }+ R0 {% ~7 [

, \* N3 h6 q' R* H/ [' |! X9.以下哪些面向对象的概念无法在PHP4中实现?1 M  W) L; y4 s2 Z6 H: B1 f
- m$ J: _+ t# d" ~
@抽象类+ v  L* q: @. t
@Final类$ c; [% y8 N/ C1 O! w9 @4 Y
@Public、private、protected(PPP)方法
3 s- x, P  A1 D; Y3 U, v@接口/ Y0 R4 o% _& ?8 x+ m( M

: T5 e5 @! q4 r4 ~A.抽象类  _% Q" ?3 u; g- ]& C
B.PPP方法
9 V; }( n" D: j, wC.PPP方法和接口8 `# `) C; N% g: b1 E- j
D.以上所有都不可用+ L- [! K2 Q/ |9 W1 h# \
E.以上所有都可用
2 b7 d( ?' H% z3 M" @" d7 ?" U" i) s3 v' E5 w+ r

& r% D) X% V  r7 _3 x: K10.如何在类的内部调用mymethod方法?! M! ?* z' M- b# }

0 p! w7 y$ U& G% `A.$self=>mymethod();6 m" X6 S4 q( g' a
B.$this->mymethod();
# s% V+ |" ^, X9 g$ `C.$current->mymethod();* L9 y6 e6 D( Q* {: x
D.$this::mymethod()/ Y* \, B0 [: X- D, Y. l, o8 e, `
E.以上都不对0 [0 F' H- h# v0 T7 M! N

4 B& @2 S" ?6 _% K' H$ V1 Z  w& D0 ?! K
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
* m! R- }  d: L1 {0 S4 f. EB.Null
& N; I* {0 Q2 K  \" FC.Empty
2 J2 I# i  q# _! c# tD.什么都没有: k5 N  _; w3 C; G. b8 d, }% w
E.一个错误
, [; ^" Z6 z6 }( H4 z) q1 x1 g
$ u  j: c1 O7 ~. m# W4 V. o# O8 f! l6 q& s
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. Q7 |' j6 \0 L, t% wB.5
0 B5 G; H4 D& l/ R3 [5 y4 HC.2
1 s) ?4 X+ x4 O/ V1 cD.Null" U, J6 W! F4 D: F/ s% T
E.什么都没有
. o# G1 p/ L2 G2 P' E. s2 @7 b' ?2 A1 \' R0 J1 N% G
) d( e) t4 B5 W& G' P6 H$ b3 d
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% h- F$ p3 q; l) b& _8 q7 I
B.10
- W6 ?( _5 V5 K" r* x7 lC.什么都没有/ R% O. q# n! m
D.构造函数将报错
, e* S1 c9 q6 p* z8 KE.510: T+ ^$ l5 n9 H( G: S! b
3 l) Q6 f# @: @) [4 p& W4 m' G) B
- M8 @7 V! V3 I' ]
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函数必须返回一个值
  s" T5 F" z, W  Q% nB.reduce_fraction函数必须接受一个整型值8 K/ v* X3 a! j! p2 \
C.gcd函数有问题
5 ~1 I1 p1 N& F8 hD.必须通过引用的方式传递$eight_tenths对象
6 a! ^# n5 N/ j8 E8 mE.对象的实例不能传递给方法以外的其他结构。0 f( m% p! N) S' N1 c* X# U: }
- L3 A$ ]: J' X# `4 |/ T1 R

1 H, L- M. n: @- a6 ^15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法
8 m) x0 ?& I7 y+ ^' n. o* s/ ]* WB.生成myclass的实例并调用mymethod方法' X$ g( H. l7 t6 p- B
C.产生一个语法错误6 Q. M2 \& Q0 X' M8 S1 ]1 K0 B
D.默认myclass类最后被创建出的实例并调用mymethod(), O. b1 a5 k* i2 Y1 ?& f% A
E.调用名为myclass::mymethod()的函数6 b) P# E. F9 Q, w

, u* l* f0 U) L6 N. i
& d) K. q6 O/ k: p16.PHP中有静态类变量吗?
- g+ n2 f! U6 Y6 m6 D
" D) a# e9 Y1 iA.有
- w. q9 w2 y1 M& mB.没有
7 l" @+ O- N% T9 `: J/ Z6 k. L, j( {6 e" n% j  M
2 a4 e/ n. e# q+ p' `
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, w: Z) Q+ H2 O* S. \1 p2 a
B.2* I% W- V& K7 D9 x5 u
C.一个错误,因为没有定义a::$myvar
& M& [1 K3 T5 n( z7 {( \D.一个警告,因为没有定义a::$myvar
" s2 K3 P6 a* y1 Z6 h5 sE.什么都没有
7 y# L( k9 n3 }: h
: E6 h+ J& d# u4 ~6 u( t2 ?) f0 H& f
18.如何即时加载一个类?3 V3 M& V6 p& {. o, C' P2 [
% A' {& B) m) D4 Z$ D+ g
A.使用__autoload魔术函数
0 G+ ]# T: b  w2 ^B.把它们定义为forward类
. }; Y9 z  A! t  `/ q+ YC.实现一个特殊的错误处理手段9 j, L; N0 o; `6 F
D.不可能' `- c( w9 P$ f
E.用有条件限制的include来包含它们
, \- v9 A+ x3 ^3 e, s! J- x
" Y) b/ E0 `2 u: J5 j9 z7 t+ s6 Y- ~) K  H( a0 S
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
1 B) `& x+ n7 U5 o
) j0 {2 L% G3 u3 R  o    答案:__________
" L  H. o! n% v% E* _) _$ S8 u1 v5 J# Q# h

  Z# t* X/ q# z- u5 q2 K+ ~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 called7 }- y- Y9 c2 ]' P
B.一个错误2 A) N& j7 p1 V1 ~: a
C.一个警告
7 _4 T* b4 n: C5 U, MD.什么都没有- _6 L; d: l& p( H" n- Y! j

0 Y1 B; \/ y. i) S0 l
( T: C3 T$ t2 ~6 P; u1 M8 P% |
- m5 }9 m& ~9 o答案速查
( A% @# s6 @5 b1.类/ t/ z/ F3 \2 C1 S2 D% G) L7 Z
2.BCD( i$ P' R( p7 A7 l
3.C
9 e" r/ P. t1 b7 T4.C  D, c. Y" |8 P6 h6 A- X
5.A
6 u" q$ A& w- z% |7 x7 |- ?6.C
& F- Q' f  _' B. G7.C
; r( U# f, `  C) i% g8.C8 {4 P$ Y8 k8 ^6 T1 Y+ C
9.D0 I  j+ ~$ l! d. ?1 {2 E: @1 U
10.B
" G. T6 v8 Q/ E( O' N11.D, ?2 L( c' U3 h& J" c# M# Y
12.B
/ i" j. L6 v, o* J: y9 A! h1 A13.A
' W1 R, @  @2 E# e; x" g14.D
9 A0 S+ i& U; o9 J- y, D15.A
2 f: Q1 |3 e+ h/ D/ L0 m3 w: N; h" m( ^16.B
1 h" [* ?  Z, U0 f. w" L/ z* P17.A* O3 e  s: a8 M( F9 @. ?& u' s
18.D" I* _- ]6 Z- \  E' _
19.设计模式
- g, ?- N& g! j; ]20.D, D, g4 p" q: O: D8 y8 W0 p
" k* W6 k0 _: h- P, \* b4 o; ]# p: K/ e+ `

+ e( L0 y& K. A: f
. f$ k. l9 o9 j: L答案详解) [. F" q$ G; s6 a: Z2 e  V! V; F1 \

1 K3 h( z! ?' Y$ ~1 P" B1.类是对象的蓝图(对象是类的实例)。
- ~. U) A3 x5 L# ~" j# U3 \/ T' W* T' j0 l2 f6 v4 }/ j3 c
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。
6 _6 o3 Z0 q+ b3 d9 }. n7 @- o& o  u5 ]5 ]: u/ z
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。7 i# d: W7 @  Q5 y6 \6 X' h. t5 M; g
( ^+ w  T% ?% q0 @. j, M
4.单件模式可以限制一个类被实例化的次数。
: \" d+ n$ T8 |% L0 A) O/ f& T8 ]' q$ t6 N6 z8 ]& a
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。9 P/ a5 [0 ]. D. F- \1 Q: H

' b& i9 [+ G8 T/ |3 k1 b5 w3 s6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。# j. e( e* w; d3 `
# ]9 j) E; u. v2 s1 Y, M$ n
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
/ k% l1 D, l* ?" b3 b# S" V6 [7 p  [( R( y0 p
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。, d  d( B4 o5 O: Z4 I) {  B
3 d( U: P* q3 h6 Q
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
; Y) {" t8 j$ f. X( }
; r+ w3 Y% [* ^9 a0 |10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。9 A, R$ P/ q) y  R% A# U3 I
  n, Y. g, _. l2 [9 t6 P
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。# `# T; `& k( p8 n2 y
4 {) ?) n" S. W/ J& V
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
' @2 g4 j  Z, {9 T! }$ H7 s
  s1 c+ ~8 j: i5 k- Z- [! T+ Q13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。1 R  |. @% \7 f* i

$ M. s* h* c9 F3 `14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
1 r8 C2 F) \% T2 [+ M! r回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:4 R6 _2 V1 H" E% i  I+ P
    function reduce_fraction(&$fraction)8 a, A! I( f+ s. X+ B, L
答案是D。! K: T% I* J: Y' q$ v8 I
5 B: C* p5 P& s3 x# V
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。9 z" C4 v2 [. g; G4 @7 {3 N2 w: y5 g$ h

& n* f& j  Q% Y+ Y% d16.没有。PHP4只允许声明静态函数变量,没有静态类变量。6 [& n: m4 Z( T) y

3 z' n6 T9 p! }; @5 O6 {2 W, l9 i17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。+ p6 D; Y5 z; A) P) B
, `) u/ Z1 g: o  C2 F
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
, Z: c" \* U# M; N& c
5 d& \# H7 B/ |  v19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。1 N" ^# J7 Q# O$ ^  A
! \5 C6 O# i7 |) w0 ?& L
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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