返回列表 发帖

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

尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
# j7 ~' B4 y) a2 e) w: L% dPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
$ u  N" t7 t9 H本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。* ?1 ?+ D* B/ b4 K
) w+ F& [7 z3 p, q# D- @, j8 m  `
问题
/ M  r7 W+ V; o* Y6 o2 u9 R5 X: j3 ?( O& u% t( ?8 S5 k
1.对象的蓝图是什么?
! C, m1 y6 ?; q/ a( R! m6 g* y& T/ ?, E7 c/ P
答案:____________; t. X% I- w% y* F/ X

! y+ a$ D7 p& C4 ]  Q; V# s9 n9 `" k2 d  B" r0 b5 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
8 V9 T$ h+ Y/ X- g; VB.b
* E- M8 E+ Q. y- ^+ C' nC.a/ L2 T. p: _4 d, d2 {; M8 L
D.d# x. @9 [0 b% o7 g6 D- U: X" x
E.e
# w/ n7 C) c2 X, J5 \: V' u; a5 W+ Z8 c* y) p' s. K
, _3 E0 g2 j; i* S: I
3.如何让类中的某些方法无法在类的外部被访问?
9 n2 ~& L" n7 X% `( \5 u* q2 [! ^, R! O. a' E
A.把类声明为private$ L' f: K' e: e8 C3 P- l' a
B.把方法声明为private
* j  Q/ w2 {6 d7 U1 L, yC.无法实现7 x+ u& ?/ [- G3 a% l
D.编写合适的重载方法(overloading method)
2 d& S+ v0 e, }* J, f7 a! B" ?( g" r2 X* d, j! L# _
8 U# |8 r$ ^) |7 ]+ \! Q) S: Y6 G
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?' x9 F- x4 |4 {+ Q0 P' R" i
- t0 _. I, q& {; }1 P
A.MVC模式' @- [: h# l$ e9 b& a3 Y" T) e) L6 }7 a
B.抽象工厂模式(Abstract factory)! U: T1 U( U1 g' X8 `: O& @0 b
C.单件模式(Singleton)
' h" n' Z& b: ^9 \D.代理模式(Proxy)
; _1 i. {, C1 `! KE.状态模式(State)! u  B) `' n. e3 [, B: v

' M8 b7 c* z  F/ T  ^! a& P$ f- s2 P- l
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?; K5 f0 R: C3 |. r) y  u
$ f7 Z/ q) B* L
A.1个, N  p  o# ^0 y* U2 T
B.2个
! e  N0 `5 b$ cC.取决于系统资源
$ X- C/ M+ ?+ Q+ }/ ED.3个
8 _4 h- w9 C' G& jE.想要几个有几个5 u* W7 m( l2 N3 w5 U$ A

( `- m4 j: w6 Y  e' |5 g
, d& l& T5 L+ b- d& G3 m; 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.多重继承
+ {- `7 x' D$ @% ^B.接口
; _; ?7 ~: b) x8 ~; F! xC.抽象方法
1 Q' \2 z0 i4 @% _+ }5 F7 B+ ED.Private方法
: `0 T7 U4 ?6 K7 yE.函数重载(function overloading)
, L2 ?5 Q1 Y; N/ ]9 y$ x# Q
8 G/ Q  ^0 e- t/ p9 }7 w" S9 z- j" B* x3 h
7.假设定义了一个testclass类,它的构造函数的函数名是什么?" D/ h+ t' T7 g! n' s

% ^8 X; |* |0 C9 z6 `3 Q: lA.__construct; @/ z* B1 p" C5 S8 U6 e
B.initialize/ B& I+ ?3 w+ p1 m& m
C.testclass
! ?: l( z2 @; q2 c3 mD.__testclass
  S( u' C- O3 C& @. w" B7 vE.只有PHP5才支持构造函数" P; F2 U* R; z- S& `
2 t2 c! s0 R. Q  y, K
" h: z0 b( ^- C% T
8.一个类如何覆盖默认的序列化机制?
; S$ ~0 N* S7 C) ~6 G+ ]! k3 G  [" c3 \) e% z. K5 g  h0 e# d
A.使用__shutdown和__startup方法& y6 P7 j6 P1 R
B.调用register_shutdown_function()函数
; B3 E, s! C4 I) g6 I4 kC.使用__sleep()和__wakeup()方法
6 Q  b5 v- A1 d/ K2 |0 |# ?D.无法覆盖默认序列化机制
: e+ k' w/ {% D3 I( J3 vE.使用ob_start()将类放入输出缓冲中
4 O% b' E. i+ d. G: D, m: m
3 Z% Q1 M1 l& V' p, Z, k' m2 I. X0 C# z/ s
9.以下哪些面向对象的概念无法在PHP4中实现?( F% [4 L' Z- W* C& K! b* J

; Y; r2 d/ X& D" b/ X@抽象类
: c- _: @; ?  r+ v* m@Final类
0 E* o' N6 B1 g@Public、private、protected(PPP)方法3 u* H3 Z: {2 }2 n" h
@接口( K) e2 y, e, N# c5 F
& H; Y; g8 K0 V0 X
A.抽象类) h$ q+ X. ]' r) b+ R7 n+ K
B.PPP方法( d3 _3 w$ ?8 Z9 U, |
C.PPP方法和接口
7 r, X7 Z6 r% I- K" O. ~3 fD.以上所有都不可用
5 F2 l3 C/ d$ B; {# \; K7 LE.以上所有都可用5 e6 R  p# a1 u) s; G

& u  |$ d" }  Z3 O( b% o( h5 `* h" \/ `0 s9 D$ y" S8 F
10.如何在类的内部调用mymethod方法?. p! U' E4 ]! |$ W  z3 Y8 H% q

2 d! n' V$ K$ E. v- _# u2 ?; |A.$self=>mymethod();
5 b+ G1 M  L; M2 FB.$this->mymethod();
- `1 T8 J) _1 _' O8 Z# r" e' a& RC.$current->mymethod();& _5 e( J: g' S$ O1 F9 N0 [
D.$this::mymethod()
/ g  s7 V, a/ o* Q2 eE.以上都不对
7 t3 H0 v8 H6 O1 X) K; C7 U
; l. x; p' T' w% p% H* @! O, h2 Y0 p
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/ ]  P  K$ ]6 w- m9 S" ^
B.Null
+ D1 f- a) n" Y- @C.Empty
5 q' t  {$ `4 B( KD.什么都没有
  m$ K% ^! t) L# i, m5 e2 AE.一个错误
4 D) T- K3 }$ ]* ?7 y3 Q; Z  J- U- u
0 w" n' C$ H$ Q- Z  _/ \+ P0 o
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.104 e3 H, z. f3 b5 F' `0 ^
B.5
: P5 [! ^( m" w3 \) pC.26 f6 K3 v) i: l2 l% I
D.Null
, Q6 B" e1 ?% Q, e: @2 ?$ W' nE.什么都没有3 ]$ `: q+ t5 `, T7 K; Y  D1 H+ z

3 x' z  h1 g/ |8 }2 A1 m: m+ z+ p3 w1 k1 m0 Z' W& \6 m# H4 W' ^
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
* @2 f7 ]  Z' M& s, zB.103 ^* Z2 c- t3 s8 I
C.什么都没有" S1 _, ]: Q( w
D.构造函数将报错
1 e  t2 j. \2 f$ E! j0 V3 `E.510+ A) k, }" f, {2 Y, [/ E
% f7 H2 E" A7 N# }4 j% n4 Y

. F; N5 t3 f- y* G, @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函数必须返回一个值# U2 L1 Z4 l" ]( p% j+ w
B.reduce_fraction函数必须接受一个整型值( u, H: p( n: M
C.gcd函数有问题( U# D2 t# m3 u" D/ T+ ^
D.必须通过引用的方式传递$eight_tenths对象% \' M& m; g  U5 q0 Y! N
E.对象的实例不能传递给方法以外的其他结构。$ I/ L( {; {- ]9 e+ ~8 A, i

: H$ E" T! M) `/ f
+ n9 e$ G; B* @) F15.以下代码是做什么的?

  1. <?php
  2. require_once("myclass.php");
  3. myclass::mymethod();
  4. ?>
复制代码
A.静态调用mymethod方法
) E! E( f& i  }5 T5 Y5 l3 vB.生成myclass的实例并调用mymethod方法
* v1 ]& [# s' b1 P- NC.产生一个语法错误9 f( E& r1 d0 \) O: l
D.默认myclass类最后被创建出的实例并调用mymethod()
5 z3 j$ e5 b# D7 T" ?' t7 A4 rE.调用名为myclass::mymethod()的函数3 X/ u1 i* T, n+ y0 s& y$ ~, b: d
4 G( T* M3 P3 f, x; l: T8 w

+ O: m3 ^3 C  A16.PHP中有静态类变量吗?
6 v8 c7 v9 ?5 w4 U( Y& A  u9 A, g3 i. a+ n+ [6 b: I4 i* m& m- O( M
A.有
# F" I/ U0 b; t5 DB.没有& y" X- Z5 A+ `
: _% C0 Q% V0 v8 [' l& z8 v2 Q

( \! W! p! T2 a6 M17.以下脚本输出什么?

  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' A3 p3 M+ D0 S9 y2 x% V6 ?
B.2
4 ]" P9 n5 T: a3 x- x/ @C.一个错误,因为没有定义a::$myvar+ l9 i) c) }3 R1 I( V
D.一个警告,因为没有定义a::$myvar
/ S- s/ ^$ I9 e' h  L* @/ wE.什么都没有
/ F9 \1 f+ M- J4 A; {* a
% D. \* K2 m, ^5 i" r* K
, a, c1 e! S9 C8 w6 x& b* U18.如何即时加载一个类?
4 s* @1 W) |9 Y3 E/ O8 i  w/ C$ g; f& N5 I1 Y8 g6 v* I
A.使用__autoload魔术函数$ r0 D* |% }" O; a/ k3 N4 b$ ^
B.把它们定义为forward类1 |4 {4 f# @  l: ~$ G* P! r
C.实现一个特殊的错误处理手段
1 E5 Y* V5 {$ }2 K" R& K9 vD.不可能
3 N  ^$ p' [5 v% oE.用有条件限制的include来包含它们, v- [1 b- j. N, r% u
& m1 e8 ^: |% o

0 b! b* c3 B1 o+ A* r19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?& z) T8 @! ]* _0 \
# |: j6 Z$ @3 [4 _
    答案:__________2 e% @1 D) s- n$ W7 @

4 A2 A; e$ Z2 l& t# `7 P8 p, i& C8 u2 @: C, }# \* H6 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 called
  f4 Y6 i! u, ^0 [5 t4 bB.一个错误. J! `5 Y& K% n& Y" m& v. Z' k
C.一个警告. o  Y0 k6 O- j
D.什么都没有
, X7 q, t" K7 q# j7 q: ^( z3 k9 `; e4 w- ?; r

% t( y. E/ A1 l% B" ?6 _+ q! k
3 ]$ i6 D% C$ f7 u2 ]4 S) Y* e答案速查5 `0 g" s  v' y8 u  B% |/ s
1.类6 b. k; t) `" k1 H
2.BCD
0 m( r# t6 [' J/ Y9 M3 }" b4 ^3.C
, k/ N  z7 F8 D2 R9 r4.C
% B4 q$ n! _, ?6 ~& H3 D- ]# S5.A6 M+ E. D* ~8 T* e" @
6.C
  `  x% h* s+ a2 D* z7.C
- L% S# Y: g1 x, W# i, O' g8.C
7 c) C1 h9 S& R# r1 R9.D4 g1 A( t. P; A$ Y, }
10.B
' x5 v; b8 r" ^$ n1 j" g0 a11.D/ j1 @8 g1 a  t( c
12.B
& V5 d" ~, W9 i" d/ E3 t( a% j13.A/ Y1 m* x" J' e3 ~3 |$ a+ i+ M5 w
14.D
4 |' z; \2 l' _+ o# z. ?7 ]0 R15.A
7 K! ?4 d. \6 u4 Y16.B3 M, ?/ G* {2 ^2 T+ V# c+ R
17.A8 i) n3 W8 S, q
18.D( b1 c$ C3 G0 W/ `
19.设计模式8 L. c; K7 p. Z* ~5 p: k" s) c# c$ o
20.D
+ x7 \7 o  H4 b" Q. g- S
3 z0 M9 p/ q6 h5 g2 q  S7 X- U+ W. J7 z' e/ ~
5 ]. u- [$ p) W( n# q6 W% b
答案详解
6 c. n0 U9 q8 e$ L6 t4 ?) y: u$ F! t3 ?' @  R3 k
1.类是对象的蓝图(对象是类的实例)。2 P2 a% N2 ]) A
. E- S; Q# Z& J% f
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。1 Z2 I6 o! R% a2 r- A3 \9 u$ \" n. m

: l9 Q, k5 l. t6 |3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。7 ]% h$ G1 f( a/ N) q+ r  U' w8 P

. \" n. c3 Z& ~' Z: O" s0 r4.单件模式可以限制一个类被实例化的次数。
7 s* E$ j& T/ Y4 V. y, B) U+ A7 A4 D  D
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。# T( l. j9 b- x3 `
+ n/ I) O( w8 d7 D0 z) H6 C3 L
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
+ M6 Q% u: h: b! b0 b5 f7 ^* r
% J3 [# x7 M7 n0 d5 N1 I4 n, ?7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。, M5 W$ ^' }. S/ ~3 V2 M

1 {% ?! \/ p; b3 U' _; j: I8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
% z/ M2 Z: U) C7 a+ G/ |: H* G$ k7 q( O' r9 y- y5 |. {  Q2 H
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。* N- t9 {$ A# k# h2 w6 `8 ~
4 I  X  t0 u, e% n7 O$ b1 |& h
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。1 \" m. C& y$ c* i7 t9 e

: u+ E1 p! y, D3 |* x0 h11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。2 G9 `$ c, r8 a4 Q. p
8 P- _; W4 e5 y- h- Y/ O0 L" Z
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。& Z5 C3 I7 ]6 _; e
+ D) M3 B6 Q) d
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。. W/ ?6 l: \- ]/ J1 ^5 q
- W( k0 c3 b4 ^% }& t
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
3 H5 ^( s! J' v! m回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
/ x: {7 T) t, p, ^* u    function reduce_fraction(&$fraction)+ L" a6 M: p# f; I
答案是D。# i# b& S) t0 k0 R1 v: J+ R& W
& @" _$ ]& l1 p$ O; E5 C
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
. d: S$ `; z$ y" Q, W  H# J5 X: l/ U7 ?+ Z! x# C6 ~- F
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。+ A4 H) f8 W, Z0 F  x
$ x- _" o4 v& O: f# H
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
  V6 O1 ]3 g6 v, {- \+ n# n( z& K2 r9 x; _' G2 r; z# D5 |% n8 L
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
" h1 b0 M9 L  N+ X, m5 a* }5 l% c, \* \$ F8 a
19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
. C2 v7 m4 @3 F6 i3 q
! f% k, @: o" Y  u20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。

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