返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
- Z' U- O; P; X3 RPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。7 T9 g5 J9 e3 H  C9 y# p8 i0 r, g" y; W
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
, n6 j0 l; Z$ j& x" a; d. F* `
4 `: i3 U& C. K问题( I3 G: ~" q, n$ K% h

( k* w7 ^1 m) N) t8 D: M1.对象的蓝图是什么?5 y! N, B/ p7 P+ [; C
. V' w  }! H; Q) V
答案:____________, t9 T( i! I* V% `' j1 u* n8 J

5 P1 F- w  P) Z% ?
( [$ s# P# Y* r% s* @2 a9 W6 R2.以下代码执行后,数组$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* r9 m/ C+ O* W4 _# h
B.b  w# f$ Z5 F6 T5 Z
C.a
; h' G4 q1 N  r$ AD.d, K' v1 M$ {4 d$ F2 t# h) b, l. q
E.e
* h/ z; L; [/ V. b" y, j" Y8 H
: a* b$ {1 m. c& S: b& ^& L! b, E& _3 j  q8 ?: j$ B; T- k$ z
3.如何让类中的某些方法无法在类的外部被访问?' p& R" b5 Y3 N& U
3 z* n8 {2 M) E8 L
A.把类声明为private3 t0 @* Z& h( l/ N9 S% M
B.把方法声明为private  W9 A% C0 Z/ {" h1 X
C.无法实现7 L( e& t3 R( o: a  l
D.编写合适的重载方法(overloading method)
1 M, Y3 g  }6 o0 z2 O3 H" a
+ u- L7 P: y# w' a' W9 k" m: p) \6 P
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
- p) g  `- ^. x. c( l3 k
2 A5 b7 j$ t7 p: W' gA.MVC模式- n) W$ d, `8 i  ]/ }2 B
B.抽象工厂模式(Abstract factory)" N  l5 H  R3 |; Z3 {- E4 b! F' d
C.单件模式(Singleton)' ^1 s" j- }. R/ W
D.代理模式(Proxy)% g# s" P9 }5 G6 s
E.状态模式(State)
" L" u5 U) B/ S# a* u8 ^
% [& _6 V/ i) m) A3 O5 }. J$ j  h$ p; D- P
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
1 D( M$ B% M7 S) |. i9 i, m4 T5 @" ]) X5 v- l
A.1个( D: G" b* U, V3 {0 @
B.2个6 |* n& Z0 D9 ?/ }1 ^
C.取决于系统资源/ z% i& [+ H# |: I
D.3个/ E8 h% T. Q) N* W4 E+ q
E.想要几个有几个
% f1 f4 h1 o! \7 M* h# g! {& W
& w0 j8 |6 }! t: ?- k7 ]- {
- B" p! N1 x+ S' X% t7 h6.以下脚本近似的表示了一种在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.多重继承
% U) L% s1 |# H3 R. uB.接口7 J, Y! N3 ^8 {2 E) l
C.抽象方法& ~' o4 S, a8 Y1 J0 m( L/ O& [) p8 [
D.Private方法
# w0 i: p0 ^  D( F- R: {+ B: Y( B6 q6 [E.函数重载(function overloading)5 D5 F8 e2 ^3 F$ W
9 h" _* c) B5 t

* v5 K5 J( h! m! T/ A5 b+ E, u7.假设定义了一个testclass类,它的构造函数的函数名是什么?
$ {3 ^1 z, ^  q
; f6 Q. L: n' B; b& [A.__construct
* F2 j; t$ K; b. R7 Z0 H- w/ ?B.initialize
  g, N+ l5 g! c6 {C.testclass
+ r8 z! y) z* [/ @- DD.__testclass& h7 _$ O$ j; k5 s# K; i8 o* b
E.只有PHP5才支持构造函数1 p4 S, i1 b! A. S- i; E- g
$ q' ~. F1 r0 x% E! }# O7 `" N8 Y

5 n  l  b7 w% o% s( @" p8.一个类如何覆盖默认的序列化机制?8 J. G1 [: {. J+ v( S3 ^

9 ?# a4 v  J6 R# m/ eA.使用__shutdown和__startup方法
4 U& `  o( }: w. m3 ]' l" ZB.调用register_shutdown_function()函数6 d2 k. Y; z2 W$ Q% p
C.使用__sleep()和__wakeup()方法, _+ r5 a) V% \* u" A5 T
D.无法覆盖默认序列化机制! Q' O% v9 F3 `' m
E.使用ob_start()将类放入输出缓冲中
3 u& o, v: t( D( N7 e4 Y' v, Y% n: N% s' V$ {+ e% J, X6 l

5 [8 v) Q" D$ Q3 ~( D: x2 F: m6 R9.以下哪些面向对象的概念无法在PHP4中实现?+ r3 @' ]( U; a

$ p: n$ V  V  t! Q, X2 K) R; x@抽象类
% n7 w5 f5 w1 k4 i@Final类
  _  X( }- K# n& S% f# t@Public、private、protected(PPP)方法
6 Z6 i7 N4 ?) o' |6 B( F  v@接口" H; I& X( U8 l* W8 d* G  S

( T. K" ^. U6 c7 |+ p6 y, GA.抽象类
& ^2 y' K, i0 x+ i: Y% c" AB.PPP方法
1 x: r) {" m2 l4 {' l7 W+ x7 NC.PPP方法和接口
' _& T8 A& m' U+ V" k0 I, ^D.以上所有都不可用
0 ^6 b# L$ U" U  ~- X7 sE.以上所有都可用
! [$ u+ q0 @7 e1 E2 z6 |9 D" ?
4 I% o+ N, B$ L# b9 J9 b
4 O8 C5 C. J8 d6 ~. I10.如何在类的内部调用mymethod方法?7 q: n% K* P' }. q0 I# A7 ^4 @
0 f/ ^2 I  m; ?& Q$ N* y, Y
A.$self=>mymethod();
  ?0 b6 H+ g8 Q1 |) LB.$this->mymethod();" A9 q. U3 P. F% b
C.$current->mymethod();
7 c$ @9 Z6 k$ N& rD.$this::mymethod()9 j0 `/ n+ M: z, ]
E.以上都不对8 Q* Y8 c0 E1 N% M

! C" A6 D! k5 n' ]+ L+ f( u0 `, h1 q% h* k+ y
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
( i: h$ [( y& YB.Null. E) x9 J7 K* S
C.Empty
  ]4 N5 H5 z+ r5 J/ iD.什么都没有
$ l; n# q  g! i% \. J# I6 ^, X( cE.一个错误
- @- g" P! a, _! y- s" `! S9 T$ l9 R. g7 A

( [6 N2 U5 q8 m4 W. b4 W7 ^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
# r( r1 k1 m" h4 d2 O, Q) lB.54 o: C5 T8 _& A
C.2
8 m; Q" [* p8 C4 w' [: J- yD.Null
- e, \9 v  a3 z& R' G/ A' O! nE.什么都没有
' u: E3 k4 k5 w3 A! i) X  m4 D+ n) R1 L6 {; B

8 g: |6 H9 q% B3 t) V! ~# |1 f, n13.以下脚本输出什么?

  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) E9 x. ]/ a6 ]5 ]
B.10
' A* k/ F2 i0 X- q( a- I( y' yC.什么都没有1 N, s9 K6 q9 C3 c9 K
D.构造函数将报错' \5 w! ~% u4 [7 P2 F% {; z, {
E.510
% [  j4 e6 s, g, h* j+ \4 b/ t8 e9 \' C& J& \5 S' g2 @
! L) v: S6 j3 r8 N+ U
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函数必须返回一个值- u9 R6 W2 |- y0 G" s1 T
B.reduce_fraction函数必须接受一个整型值/ A$ P* ^; [  }8 x; m5 ^( y
C.gcd函数有问题
: }( A+ u: x* \) E; d5 X! O+ VD.必须通过引用的方式传递$eight_tenths对象, s# Y* {5 W: V( k1 P! R5 G
E.对象的实例不能传递给方法以外的其他结构。; V- L. {  q2 Y
, J# W' G7 |3 o# ^  J6 e! K

9 Q8 H% s6 q# d4 r9 E$ a15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法
$ g) u. R0 L# J. w7 G% y2 ZB.生成myclass的实例并调用mymethod方法
( N* t9 J0 F; cC.产生一个语法错误) z, f& c6 Q  e! _; ?5 w* Q
D.默认myclass类最后被创建出的实例并调用mymethod()* G, _4 u6 B; a, y, _
E.调用名为myclass::mymethod()的函数/ _) c- h9 s5 J  J. v
" r' v# N0 {! j8 G$ n

& C4 |  L' H  Z+ N% j& u# }5 a16.PHP中有静态类变量吗?8 @- m$ i% z  n. [  d' J; S
- n2 ~: ?7 a0 r5 [, P
A.有5 l+ i1 s' L3 L% A
B.没有+ R6 A) z* d/ X; a, |
: |, P7 d* u; E* Q5 T8 k2 V" O
# q+ I) `3 w; ^5 Z
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
& F: U" x# e; g$ \/ @' OB.2
0 H% ~  w% d0 r+ aC.一个错误,因为没有定义a::$myvar
/ W. B- u3 Z& B8 b+ GD.一个警告,因为没有定义a::$myvar
9 L) _0 L) \6 N2 m* PE.什么都没有
+ f& _9 T1 J1 {: c' e$ @1 Q4 B- x: Y& @4 ~
! p( }+ a& O# [9 {  U( M( |* S$ {  u( ?' z8 B
18.如何即时加载一个类?
6 n# j) n( ^8 ?; {/ R  v2 T* x, i8 p8 J1 c3 c3 s
A.使用__autoload魔术函数3 L  S9 N( u2 ]% U
B.把它们定义为forward类* @& E' A6 v# T3 V4 M9 M
C.实现一个特殊的错误处理手段7 s' l7 r0 B0 c# \3 z! @
D.不可能# z4 c4 ]% o7 k# \4 R2 e
E.用有条件限制的include来包含它们
4 \0 J9 B" H: R( R2 i
% J4 P: z5 l3 t* P; d
3 N) [3 \, }& o, r: N/ b4 O' \19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?% f* y# R, N1 o, |8 _& v, ^
# P$ M1 `2 Q- Y; y/ y
    答案:__________4 t5 Q5 X. f' o( {% b: h7 ]

2 h! d1 @8 y3 ?2 Q4 r) o
" M& @+ _4 J4 L# S* C20.以下脚本输出什么?

  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
- Z$ o0 v, a5 O. d+ QB.一个错误
9 a) m5 l0 P6 ~C.一个警告9 H9 r0 z: ^: a# t3 J+ v
D.什么都没有
9 M5 [7 C( m9 A+ r( d
) P0 ^  \7 P1 N3 ?/ X3 j/ P) N* S! i. X' v

* m! r0 U! ~; {! w答案速查/ n# N* H9 V, |4 P3 S" X. [
1.类
/ v3 t* @3 p, L" H) ~2.BCD5 J; W& x  H* f% K8 o7 _
3.C# F, o7 v( G; w
4.C
0 ]0 q+ Q' f4 e0 i; r7 h5.A2 E% f, q, u) o4 Y. }
6.C4 _8 {/ M' m% Y5 `
7.C. R/ N0 g0 J+ y0 f$ a
8.C
% a" D2 x8 E; K( {( a8 q! X8 j9.D% W7 n( x  _1 f- t0 I6 x. r
10.B
0 a7 P1 T% t0 u2 {6 E11.D$ y9 [3 d9 U8 G- Q3 {
12.B/ X  z& F7 Y' p( k; L: P# `  C2 D1 S
13.A
" i' v" Q$ W0 y& O. ?) @  C& O14.D! ]+ k  S; K) ^1 A$ X
15.A7 N5 L9 v" E- a+ k( X$ T) N. m' ]! v
16.B
1 u2 q1 m1 k  I% S1 I17.A
9 [$ m0 d; I# }2 C; F2 e  t( k" n18.D7 ]2 l, y3 m' n  {) A
19.设计模式
* t+ p# r* G+ Q) {3 R0 N20.D" h+ B2 X6 @/ {5 k  \
5 |6 B' G# \! D8 Z
" N+ z' F5 @' f

0 j5 ~% y( u* K答案详解
# X( G. d4 U$ L6 u4 n* c( j# m
# E% c/ `' k+ {! I6 R0 {. [0 V1.类是对象的蓝图(对象是类的实例)。
* P4 f4 M' ]) n
  y' @( D; \" T! c0 H9 P) g' [6 r2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。0 D: M" T7 `5 }$ h2 Z7 Q0 `: T

/ `$ ^" ?$ K# r9 Y3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。# g- O& V; G; b0 g' ^# `

% r$ Y' B1 [; b; r4.单件模式可以限制一个类被实例化的次数。
8 |7 S+ X- y4 T7 g. N2 Q
8 z3 d% Z) c8 F" `0 {/ ]8 j5 j5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。( N" P5 x8 X* e, R  N9 y
2 G4 I! F# W$ y
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。) [0 n/ H1 [4 w, g0 v

" S& F4 R; }6 t# e: E9 G; L3 W7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。$ _; m- @2 r5 L9 L. x

9 g& Q6 ]- n0 h3 s! n8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
  l% [% N! I- v* y: U& p& a
% |* D* c7 g/ l$ [! M9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
! Z0 P, V) g* u1 E- B: E3 h% |# [' {+ ]; J) }# e% z! z  O
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。, `3 ^0 f& W* @' h4 T  H& v
$ g; L7 B+ H0 [. a& \  B# f1 ~  O
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
/ L/ [8 V5 F; K( M8 R
: s9 t0 @+ b) B- I; ^) f) {5 V2 X12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。" w; ^# d* u8 S+ X8 ]% u5 a
3 D0 T* Q6 n6 [  n
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。1 _5 D8 F- G; a* T& Y( X

" Z# Y2 W2 M8 {8 m/ m1 w8 l14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。- t0 k1 q! g. O" z6 [* g* y/ J, z
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
; c( [5 H7 N2 l    function reduce_fraction(&$fraction)
; y" U9 s" `2 L  W答案是D。3 W: @. n9 b, t+ _8 t% J

# T# D9 x8 b( r; O: C9 k15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。) s) i2 @4 ^/ L- ^- i
) z, J1 A( \1 X+ s: f
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。( K  B* t) O: h2 Y( G3 K
3 ~8 F( E+ {! ~$ b$ ^
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。) S+ L% s3 w/ N1 F; w+ s+ n. {
( R& b! b5 I, {& E' O6 r
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。6 u" x; H7 F# g$ i! X4 ^4 ]
! {9 g$ R! ^$ v8 v
19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
9 d8 x: Q) _  v0 {" V9 W" \$ c
% f* \* b  N! e' N2 j20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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