  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14247
- 金币
- 2414
- 威望
- 1647
- 贡献
- 1362
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
3 Q5 a3 U6 G+ DPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。' ~3 t* ? j* k, ]
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。* C/ S0 p* M2 G2 v8 L/ ~, w
& C* S" F" r) T
问题
" D S3 c$ B/ P# s; c1 R; M; l: j- G- z
1.对象的蓝图是什么?
7 O h" d( l; c, Z. }& |' F0 p' ?$ z: u! ^
答案:____________
. r$ C) l9 M) M `1 y4 J
, W0 ~9 G! k! q% c: c( S$ @" i2 Q, k1 o$ e2 H. p5 m
2.以下代码执行后,数组$a->my_value中储存的值是什么?(三选)-
- <?php
- class my_class
- {
- var $my_value = array();
- function my_class ($value)
- {
- $this->my_value[] = $value;
- }
- function set_value ($value)
- {
- $this->$my_value = $value;
- }
- }
- $a = new my_class ('a');
- $a->my_value[] = 'b';
- $a->set_value ('c');
- $a->my_class('d');
- ?>
复制代码 A.c
7 Q/ q9 x6 {- L5 fB.b
6 D! ]/ Z: A0 e7 c. Z; L2 `C.a
6 P) d# \" [, s! s$ t6 oD.d
8 Q8 p' y9 [3 `; o9 B8 a3 z( CE.e+ E. F- J5 H8 Q( d# S
; s$ v1 }8 k- }, S% V4 d
9 ~* ~8 n# N8 S/ b6 {- ^: O
3.如何让类中的某些方法无法在类的外部被访问?' V- j- U4 S/ Q+ c7 e7 V4 {7 H- r
1 [- J8 \, a0 O& ?, ~- c/ H n
A.把类声明为private4 j0 [1 Q9 C T9 S, ?4 ~1 C+ B- l
B.把方法声明为private
% t! {- F$ [: \. EC.无法实现6 U# l6 _1 x4 d7 I8 a/ x2 N% O
D.编写合适的重载方法(overloading method). l7 o$ Q! ?* {( v
9 x7 H7 V6 C3 l7 ?1 x5 x' s$ m; P
5 {) S4 v6 R4 |9 n; ?* ~4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
7 X/ g: b5 B X3 `7 f- L% V7 [: i, J& m6 b8 Q* s, ?2 b
A.MVC模式$ x) ?' o! J) K$ B: q2 ?) i7 F; P' f- S
B.抽象工厂模式(Abstract factory)
3 j0 G) @! {8 Q2 w' b5 W+ ZC.单件模式(Singleton)
4 F" c: g# h8 F) D, MD.代理模式(Proxy)
$ {0 a3 C) c4 s W1 W; A' PE.状态模式(State)) V h/ s, ~# [' B+ [
- ~9 H! }. n. z7 _2 L, S
/ C* ^6 u# e- \4 |5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?" B4 E' h, {3 K1 h
! x" [* r2 w7 ^! k1 v
A.1个2 V6 B' P2 b9 n# d6 o" f+ p* F; D* y
B.2个
- q; c& @9 L; K) w# x1 a8 pC.取决于系统资源
9 w7 x# O- h5 q9 DD.3个" y( k8 s( g" \8 F4 P* z% ?, E$ K
E.想要几个有几个
$ f& A( ]; [0 m- _- p
, u* U0 Q: n/ N+ I0 X' O& U3 Q; h) S' L: P) k) Y1 n( h
6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承
- p; Y+ o! J$ R: ]9 I( [B.接口+ O" [- W9 X! y. g0 V
C.抽象方法# d- e& T$ | P) m
D.Private方法
+ r. Z# r& J4 d3 M8 cE.函数重载(function overloading), e9 B1 |: p1 V5 S* l: O
/ V! e: F; l! F0 e! V3 T0 y
& m! ~! k5 C% L( v% a
7.假设定义了一个testclass类,它的构造函数的函数名是什么?
6 z! U" i4 c9 q% W
5 d$ R n0 Q" x, x5 D, ~7 V2 E1 tA.__construct
. j" `" i8 ?8 {: d+ y/ B- b5 ?3 |B.initialize7 M# G5 S2 M' b% J- T
C.testclass
4 L& ^& T8 ^# _D.__testclass
8 z1 s0 S( L% D% TE.只有PHP5才支持构造函数! r! Y3 S" n4 ]' v) u$ j$ M1 S
" e2 A3 g' O4 l* ?, X" _
) p" g* X3 W+ [) w7 n) [% y+ y8.一个类如何覆盖默认的序列化机制?
' b' ]+ L3 k/ j8 h; A+ A1 V8 X! D- |
A.使用__shutdown和__startup方法
/ W# j, p3 D3 J) F, }" Q. sB.调用register_shutdown_function()函数( o% O/ C. E; ?
C.使用__sleep()和__wakeup()方法1 p% B% o# c* |# ~
D.无法覆盖默认序列化机制$ K& n$ Z J. j" `9 X* _' h# h
E.使用ob_start()将类放入输出缓冲中* g* R. `8 v, S i, l4 Y
& u) B9 Y1 [5 }. _5 Y
1 v& k9 q! C; H5 P* x+ ], T0 Y9.以下哪些面向对象的概念无法在PHP4中实现?7 U. D/ C9 m# t; p4 d
+ V4 K; R7 L1 N* Y6 M@抽象类
7 [3 g8 @" l5 R" ^6 c@Final类, o( X3 I) K, Y- X; I$ @
@Public、private、protected(PPP)方法9 o" E6 q' ]2 N
@接口
+ k: p- K; {0 M2 F; }1 B: n' B8 K' y/ [% o) X$ @
A.抽象类
3 D2 h# z6 j/ s! MB.PPP方法. `* \+ f, M3 B. l
C.PPP方法和接口1 l6 S# _7 g) D+ p
D.以上所有都不可用
! z) N# @! Y( KE.以上所有都可用( f. @3 V1 T- t) x: z
2 G; d# G# w- I, G% b
$ D" K4 U i4 c: b" k& B) I
10.如何在类的内部调用mymethod方法?
6 P% Y# L( [1 ]5 l7 ~6 d1 M2 _9 Y- @9 y+ F, K4 W
A.$self=>mymethod();
, ^, ~0 y/ `- s, s xB.$this->mymethod();2 j0 p! N, O4 g- h3 B; T N+ f
C.$current->mymethod();9 u, M: m3 I! H# t- B* Q% j# {
D.$this::mymethod()1 m% L$ H K& @4 a% C4 ?. N i
E.以上都不对5 e8 }7 U/ [( L6 R
6 ~( h9 E ~& \: |
- u' h% F1 u9 \11.以下脚本输出什么?-
- <?php
- class my_class
- {
- var $my_var;
- function _my_class ($value)
- {
- $this->my_var = $value;
- }
- }
- $a = new my_class (10);
- echo $a->my_var;
- ?>
复制代码 A.10# H& A5 t# i* R/ r0 _
B.Null7 L, d! n' H) A0 ^" J% B# M/ N
C.Empty5 A' `; e" j9 y& D" [
D.什么都没有
6 I& t% Q8 z/ t5 yE.一个错误
" u1 {9 C: D1 n
) B( s( R( O" Q5 [. E
9 l! K! M0 M/ K. O$ H" x12.以下脚本输出什么?-
- <?php
- class my_class
- {
- var $value;
- }
- $a = new my_class;
- $a->my_value = 5;
- $b = $a;
- $b->my_value = 10;
- echo $a->my_value;
- ?>
复制代码 A.10
8 H& J* r$ u, v( N- v( KB.5
0 ?9 X- o! ~5 T/ C$ A4 z* [) jC.2
F7 [+ ]/ r( iD.Null
- D, F9 a# z7 q2 U$ WE.什么都没有
! @, H& f7 |5 L/ h
6 Y7 ~5 [0 E. r; H5 x* A; o! Q6 b2 \$ I
13.以下脚本输出什么?-
- <?php
- $global_obj = null;
- class my_class
- {
- var $value;
- function my_class()
- {
- global $global_obj;
- $global_obj = &$this;
- }
- }
- $a = new my_class;
- $a->my_value = 5;
- $global_obj->my_value = 10;
- echo $a->my_value;
- ?>
复制代码 A.5
% f" E8 |* }, I QB.10
1 e4 x3 |4 Z% Z9 o" PC.什么都没有
) R# Y$ a, @5 H/ TD.构造函数将报错
" k8 X+ d$ G0 {( g& {E.510
" X1 b& e- S4 H$ C5 v) ]6 q
' ?, N, X5 T% `+ m) w" O/ J' g; f0 a8 k
14.考虑如下一段代码,执行时,$eight_tenths->to_string方法返回的字符串是8/10而不是希望的4/5,为什么?-
- <?php
- class fraction {
- var $numerator;
- var $denominator;
- function fraction($n, $d) {
- $this->set_numerator($n);
- $this->set_denominator($d);
- }
- function set_numerator($num) {
- $this->numerator = (int)$num;
- }
- function set_denominator($num) {
- $this->denominator = (int)$num;
- }
- function to_string() {
- return "{$this->numerator} / {$this->denominator}";
- }
- }
- function gcd($a, $b) {
- return ($b > 0) ? gcd($b, $a % $b) : $a;
- }
- function reduce_fraction($fraction) {
- $gcd = gcd($fraction->numerator,
- $fraction->denominator);
- $fraction->numerator /= $gcd;
- $fraction->denominator /= $gcd;
- }
- $eight_tenths = new fraction(8,10);
- /* Reduce the fraction */
- reduce_fraction($eight_tenths);
- var_dump($eight_tenths->to_string());
- ?>
复制代码 A.reduce_fraction函数必须返回一个值/ n+ ^: c5 n6 M5 ?1 A3 x
B.reduce_fraction函数必须接受一个整型值
! \* E% c8 w' p4 n2 D, aC.gcd函数有问题
- {4 X0 }+ z6 h; iD.必须通过引用的方式传递$eight_tenths对象
0 e6 q. L9 `3 n; r7 dE.对象的实例不能传递给方法以外的其他结构。
) N( Z& n2 p- E: n' e. T* A, r/ q7 C U7 v, A4 S8 q
, z6 ?7 p6 Y& }' n4 @/ R7 n* {. j
15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法
% M% I' [- R+ q5 {- _B.生成myclass的实例并调用mymethod方法
8 p8 `# f$ e" P3 S5 m( k4 KC.产生一个语法错误
; _' i8 ~, [$ Z1 _7 v- u- I: FD.默认myclass类最后被创建出的实例并调用mymethod()
' U6 j" `9 y# {7 {! ]. V2 n/ K9 lE.调用名为myclass::mymethod()的函数
+ [$ p2 S% U5 g9 w" l7 Z& S
! n- Q; T. u/ [) U. p& {* c' c: l- p f, u
16.PHP中有静态类变量吗?
0 h% c# B) \( d5 E
) v8 l3 c& \# RA.有
: C" O. c5 k; ?$ M2 uB.没有
- C! l1 T! a5 T+ u( q3 j3 A% H& r
$ k( O) [: ~6 i/ |3 j& S5 n& } S; y0 v, g# I* z, a
17.以下脚本输出什么?-
- <?php
- class a
- {
- function a ($x = 1)
- {
- $this->myvar = $x;
- }
- }
- class b extends a
- {
- var $myvar;
- function b ($x = 2)
- {
- $this->myvar = $x;
- parent::a();
- }
- }
- $obj = new b;
- echo $obj->myvar;
- ?>
复制代码 A.1
& w2 v z) Y' I& G; x7 EB.2) s2 p v( V, j, j ^* N
C.一个错误,因为没有定义a::$myvar( ^7 ]- f! z9 v& F
D.一个警告,因为没有定义a::$myvar
& n: p8 `# X/ M8 FE.什么都没有
( w A) x! Q0 |8 g8 Q0 E% L k4 F
: a# l- W- h8 G$ k
4 y7 i/ o, ]( K7 y- H* F18.如何即时加载一个类?
; Q8 F$ v7 L; S- B: O: N5 q, S2 H! b4 C4 M, R3 |! e
A.使用__autoload魔术函数
* O9 g; N/ k1 \! ?B.把它们定义为forward类
! Z2 S9 b# B$ e3 Y4 P& ]. r+ QC.实现一个特殊的错误处理手段- @6 P, b% [! a
D.不可能
& z% N) N: ~5 Z6 N: ?( QE.用有条件限制的include来包含它们
V# \) L# k I7 i5 v0 q* B
0 [8 C# T5 b$ L2 W- T% Y; ^- G
: q1 ?4 \) I) n, G5 T4 ^$ Q. v19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?- `. g. n, E& B
# }# V# U( s. u" R8 e: I; g
答案:__________; f. Q+ U# H# y7 q: {; U. L; C' y
3 }7 i8 Y1 o8 j' P8 o1 t& q' W4 y" h$ U/ Q) A& ]
20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called) r0 Y- m" J {# [: x1 [& s/ R0 L
B.一个错误+ d9 d/ U% T& S: c8 c8 X& ?" X
C.一个警告
9 U; X. M" S8 d6 _; z# [0 jD.什么都没有
$ S8 W2 h, K$ L0 W7 ~
8 k$ |; ~( W" s5 x, _
* j. f; C- w) R' N4 ^! w5 b! C* M$ [1 T+ `) s& S) U" t) _
答案速查
+ y" ~# E' I2 I* B1.类
" z( g2 _4 ?8 ?& s9 ~6 o2.BCD9 h( E+ { U6 j- M. w
3.C5 F% G, D, B- A) o
4.C" h2 [* e! K- a3 l4 Q! S! j9 b
5.A
% x* `! q, g" p7 E6.C
6 C/ [; G1 \3 Z1 }; f7 J, s7.C
$ S; K" y* O) k ?( b+ i8.C; h9 s) D$ O. g( y0 \7 Z
9.D& m8 k' x" h. U" y' w
10.B
7 e% [3 f! N& n* R5 F11.D, T) `* Q" g6 l9 s9 d% I
12.B! ~8 l- D: M0 ]9 a* \
13.A
# s1 B" v# o& n2 `! y14.D
! v- i, m- ~1 Z+ z, L" b- }15.A
, B* N( v0 n2 k( O8 W16.B
f& u" V* L0 H1 N2 v17.A
" W8 W/ e8 }5 d) l/ e- i" S6 e18.D
3 t+ y: ~4 m) Z0 w$ W19.设计模式0 p! i0 v+ C' x7 _3 ?
20.D$ R; E) A6 w, b& k* O
, l9 w4 p% |3 x7 z9 z9 x; L' K
0 b& Y: u% P! z) A$ N k, @/ g
6 v7 N0 Q: y3 B% ?; I答案详解7 n( Y1 D! m( {
: R# v% G4 F9 m
1.类是对象的蓝图(对象是类的实例)。
2 W( c- I- { j$ u' B/ f1 V9 b. N+ E: K
1 T; V$ m7 T4 Q( o+ t2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。+ V# x3 o$ n9 j. ?4 P
+ |2 h2 `5 |. U9 z& [
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
( q: C6 R! P) n/ y8 Y! D
" o, k0 o0 U; B! h4.单件模式可以限制一个类被实例化的次数。
) N' z |, e- C1 N0 k H2 C# w$ A/ B; Q* c; \. G, a* B& v: f
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。
. H4 g1 b. a. `! N
1 I- F6 j3 M7 v7 f/ x6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
, r6 n; D+ b! ?. z% ^0 i, @( B7 h0 J) G" f, M/ L) Z
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
; u& y- M0 I, f; k# Z" M& N/ Y, X
- g, U F9 H: Y8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。; Z5 s5 b1 W- Y. ?: H& C
; N9 b0 S ]/ w9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
+ K: i9 f) w' G8 ?6 D3 h& \+ O1 g7 G& y X6 p/ Q
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
) P% S0 c5 w$ {
* L. o! T# j! _; \) u- X11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。8 C% W ?- [/ z0 y
' o2 x6 V: u* A/ }6 ~/ M9 S12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。5 ?# ?5 p5 ^, f: G. U* E; @2 f3 D$ Z
- M3 F3 h4 k g8 g13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。5 X G }3 W! k' d: A4 F
% X5 }/ g9 a5 Z1 v6 L- H( f7 f14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
; Y2 y: l0 O) V) R; `回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:- C+ Q& e0 U4 n6 E
function reduce_fraction(&$fraction); ?! J' a+ H2 f z
答案是D。" E, M" F$ U' T. | F" H
2 w' Q @0 `; p4 |3 b- y
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。; I8 j) K4 C) @( @
" |' r+ F9 j) B. [! W% @2 ]7 A+ o. f Y
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。4 w8 O. _3 V) g" Q
3 S4 c( c0 e D17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。6 u0 L: r; p, v! L
# K+ P3 d$ I( X, l' [% H" F18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
y9 n0 v7 m W$ w- {# Y( F* f
/ t/ G3 u; v. O; z: N19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。* B) g; o7 ?$ m" G8 ~
]; F& {6 U _/ s7 q! k* F J
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|