  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14197
- 金币
- 2389
- 威望
- 1647
- 贡献
- 1337
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。/ D( a) O. ? |4 \- `5 s
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。; Z5 u. @+ X3 W# Q& u
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
/ W/ g: ]/ u, F7 M
8 L$ F" j; ]0 a问题
+ _) j3 C) _+ _9 x+ c8 m0 m) E6 Q, v4 D) b' i$ [
1.对象的蓝图是什么?
' t2 N+ W4 k0 e5 }7 X! @
3 o9 |& b9 \; V9 z- z答案:____________
9 Y4 @" z' c9 j- m" k3 C. C- `( y
/ @1 M- u) R2 _" i4 R2.以下代码执行后,数组$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
1 o; `) _: U" C2 p, b' I4 s3 ^B.b8 ~3 a8 L1 a8 z# s0 R L4 O3 _
C.a
' B* X: ~3 B8 K; ?8 UD.d6 l# n$ ^* l+ F1 M3 H
E.e
/ T9 v7 f/ t8 y+ H' h8 s& R
k1 I4 m7 E' {# \# b4 v' V2 s5 k% }" g$ A+ R `
3.如何让类中的某些方法无法在类的外部被访问?( o8 Y9 ?0 t1 Y& [0 [) y- ^& J- ]
2 Y7 j# P$ }/ {* {) G6 l
A.把类声明为private
) d3 B" Q! j6 Q5 w& nB.把方法声明为private
" N5 L2 I1 J6 x3 W0 m4 DC.无法实现& p: C, h0 `3 ^0 ]6 }5 I
D.编写合适的重载方法(overloading method)
2 h2 S& E) [! V4 r E/ l' ]
+ Q! ^2 K, y0 ^( ?' o+ X: c0 P7 X* g/ k0 V2 m; U3 q
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
5 D7 q9 [9 K2 g# K9 b0 d1 B/ m5 f. R; X) y9 A* x$ q
A.MVC模式
7 U7 H# ?! v3 n% x1 E+ F3 PB.抽象工厂模式(Abstract factory)
) j3 ~; J7 m: O6 S) K/ r# ^C.单件模式(Singleton): G+ ^, T8 P0 N2 z
D.代理模式(Proxy)
. ?0 Z8 X' c6 }- F2 WE.状态模式(State)
: R% l; m/ U% @) W \9 B6 w' Z( \$ p( R( x& a6 |
0 G; D6 G9 J/ h$ D6 M2 [
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
+ i; ]* {$ V0 J0 v# _" I# P+ f" |- r& L
A.1个) [/ ^+ i, Q$ @0 Y( P! w. ^& F2 l% I) H
B.2个
! L3 G+ N1 z1 `$ MC.取决于系统资源- ]! I+ }; ~3 v9 v/ n0 J$ ^
D.3个% d+ I. v o: p j& L
E.想要几个有几个
x. b0 X. o0 _8 ?
: g' h G2 n5 S( X' z& x- O n5 i O1 Q
8 l; T M. t3 L' ]9 F/ f6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承' B6 J6 D: ], R+ e
B.接口
( ^2 y; U5 S6 eC.抽象方法
0 B; M0 Q% _" N, W( c" k {D.Private方法
- S- v5 e5 p& V5 `0 x3 YE.函数重载(function overloading)
3 `6 [- Z& B# f- d, Y7 \
2 C% N7 ^$ _! N% h; e! S* I( ^/ l) C2 e) o
7.假设定义了一个testclass类,它的构造函数的函数名是什么?! G c4 b' s1 u% b' c6 t
9 Z& v1 W, Q1 `A.__construct
9 |9 w# w$ E- I ?4 qB.initialize
# n3 ]" @9 O" m$ R( A- ]6 d7 dC.testclass
6 A' [1 f+ J+ k6 G9 @D.__testclass- H! ~( o2 T1 r
E.只有PHP5才支持构造函数6 R% w7 @/ ?+ ?1 ^* t4 o
' g- F( t W% B' ?" T# H3 N
1 p9 r# B4 Z% P
8.一个类如何覆盖默认的序列化机制?: a, ~% U/ S' u' j
" ~4 S! }5 Q/ }# pA.使用__shutdown和__startup方法 u- O# ]; c% q( k; N" l2 n0 T
B.调用register_shutdown_function()函数
# c" v- T; a+ `$ y4 [9 L3 cC.使用__sleep()和__wakeup()方法+ i% S$ j' O6 ~% {
D.无法覆盖默认序列化机制
% i* h* ^! k# i' AE.使用ob_start()将类放入输出缓冲中- {6 {* G e# L5 H8 L- e, W1 D8 \
9 ]! r# l' E# N& S. O4 X
9 `& b2 L( `8 p1 j1 Y9.以下哪些面向对象的概念无法在PHP4中实现?" l) d9 j! z* e$ K. L7 A+ _
8 ~- w" s9 f% e; S) y0 y, a@抽象类! g) r0 R4 y x1 p% j! T6 @+ S
@Final类
) y# W& z: s4 S5 i% Q# a: _$ ^9 g@Public、private、protected(PPP)方法
9 o2 h$ v( T( e9 h@接口
: u6 X2 T) a9 e8 R8 ]0 }) f+ y! {" ]0 n
A.抽象类; y( v9 d4 L# G2 j/ ~
B.PPP方法
: g+ ?) {' W: r: |C.PPP方法和接口 ~( O: Y; M6 c, q+ p2 A
D.以上所有都不可用- N9 ^7 N7 E& v4 u# d
E.以上所有都可用& O+ ]6 y2 B) r: B+ I
D4 \5 X: G* S0 |! Y' M9 O" ^. _
) L) x: f( h4 a0 C10.如何在类的内部调用mymethod方法?
; o* I, @/ A" b% @ z) u" G+ F; ~
6 ~9 ?. S& K8 Z6 c2 p3 WA.$self=>mymethod();% t4 I8 d' l. o* g M, q) ~& m
B.$this->mymethod();" P1 S8 q0 B% Z; U# P1 [. g0 m
C.$current->mymethod();1 A$ f6 Q7 `% H( ~2 a1 R% K, c
D.$this::mymethod()7 Z1 h% e2 m9 D! k4 K4 L
E.以上都不对
( z$ g# c7 R _2 \/ ^ e y* `3 b8 m7 [9 b$ Q) W, e
( d8 m7 Y$ ~$ @. ]. h
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.102 n, j8 e; N( h# U
B.Null
S6 W( V0 g6 T5 X2 I3 UC.Empty$ K. d. X2 c4 l8 q. y" ^3 J
D.什么都没有
, ?5 g$ P7 Q, E" z7 w2 ~E.一个错误
& f8 Q9 l- n1 p( n8 d8 w* s5 N4 `) ^" m, R2 A. m1 e: E' Q
6 D4 f& a. a( r: l12.以下脚本输出什么?-
- <?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.105 k" ^$ p* c3 W4 }
B.5% S B) M; `. n/ M. K8 U
C.2, H |" W) r: i3 c
D.Null
7 [% E) ]2 P$ p8 iE.什么都没有) B R: M. h+ p1 O
! M3 L5 G! \1 Q+ @
) r$ q7 D/ z8 E9 A; ]8 t13.以下脚本输出什么?-
- <?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
8 v7 }6 Y' c* ~& [B.10# i' G- R* _1 b W. e- q5 z$ B4 W' R
C.什么都没有0 W u4 ?6 M/ L2 Q7 @- I
D.构造函数将报错+ [. N6 i9 g5 @* p3 ~* v
E.510
2 l; a- L1 @$ d; J; j' F& q" [: e6 S* r4 f; h1 ?5 x
0 y3 P( M! k" r' \1 C14.考虑如下一段代码,执行时,$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函数必须返回一个值
( z4 `$ W9 p1 PB.reduce_fraction函数必须接受一个整型值
0 L. k$ D! `$ v! g% X9 UC.gcd函数有问题
. r( i2 h0 J5 g$ H9 ]( X# j" UD.必须通过引用的方式传递$eight_tenths对象7 s2 X+ M, s+ L% U; h" b7 N! e4 e
E.对象的实例不能传递给方法以外的其他结构。
) X: h. \9 x3 ^# q
. t% N! P0 i$ ]7 R# v, F7 h& ~; V! J& i- S
15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法6 W4 x0 [& ^% M6 \5 g
B.生成myclass的实例并调用mymethod方法2 ^5 {% S S, y1 l- v7 D
C.产生一个语法错误
! w5 m% h! [3 F' q. u2 a4 fD.默认myclass类最后被创建出的实例并调用mymethod()
5 Q/ M* K0 b( n8 F* E$ sE.调用名为myclass::mymethod()的函数6 w8 H9 e0 l. |8 R3 t4 x
# c9 a! j1 _0 D. D6 i; U, {8 e* T5 |9 x" Y' c
16.PHP中有静态类变量吗?
: ~: }1 t4 F. q2 k5 h. L0 M% H, o+ y$ }4 x- p8 L
A.有
. F! _- y$ J6 `B.没有
# \8 w& Q6 W' E) U x; q7 l/ z0 y) j; Y; l3 ]# i0 W, K8 x
# u# m6 C( K( N
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
7 s8 L3 P0 @ D, k0 x7 V- tB.22 \1 s8 C6 F2 x( d) `7 y
C.一个错误,因为没有定义a::$myvar
$ T0 \+ g+ f& }5 [! eD.一个警告,因为没有定义a::$myvar) j* T1 i5 b2 {; c6 W) q0 [
E.什么都没有
, _1 w2 [ F+ C. o" J0 `1 k* e' g) v' ?4 M, _
3 `8 @" }! t" @( W1 s0 u% o; V18.如何即时加载一个类?
$ D8 }5 q8 x$ W1 R
2 G+ ]/ w' h; o& w! _- SA.使用__autoload魔术函数
( t, d/ Y( P3 g. l6 u) vB.把它们定义为forward类+ h9 l3 H, `6 U6 m1 |8 c
C.实现一个特殊的错误处理手段
. n, w9 G) P: R8 i! {. pD.不可能, y: @1 R( v( n/ G7 l, J9 X
E.用有条件限制的include来包含它们4 {, Q3 R! ^) X; F4 C, {
& z _8 u$ U4 E! f
' H! ~0 x/ v# `! D A+ Y& U
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?% y/ y$ s H% _2 B
/ o0 w4 i; }9 U) [. c 答案:__________
* W( j1 h) M1 o9 X" r3 _! W7 I7 S2 b, w" [. L
1 r0 u8 U( l* v: j5 O20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called
1 V% w! }: }+ S5 y t6 V4 DB.一个错误
( B& }+ x* E" k mC.一个警告3 H, U- O; G4 h; w* A: Z
D.什么都没有% N$ @8 S& H* K+ U: j& O
# g4 I* f& \0 S! k- _' M+ ]! |. T
0 j5 G7 e' ~ V4 r) X% m答案速查
" o' k! S1 g# c/ L1 e1.类# ?) |1 `, C6 x- m' ?; k; i, K
2.BCD
5 b/ a8 Z+ }% u" P( @# c3.C$ Y) M+ `1 K% R' O. p* s# p
4.C
+ P4 o& h+ `" m; X- h% t5.A
/ _5 k! @! S a$ R) T. y6.C
' O* \. W! a5 v/ x5 [7.C) s8 g# V5 @- N+ Y
8.C
7 I6 S* X4 z* ^5 E3 E4 h9.D
9 w+ _; L: ^$ w% h9 _: Q10.B/ t: x) e4 \' R5 W& F, l
11.D* ~" \/ d, s0 O# z
12.B9 e: M# \* @4 _; w/ a& ]
13.A$ E) C) _, E4 z, C
14.D/ ^7 n5 I7 Y% g, o
15.A
+ ]0 e, d! d3 s8 T16.B: W c$ M4 @# f; |
17.A
. ~* K! q7 e3 h7 U G18.D% B; ]- L' ]7 v/ N
19.设计模式
( ?& K: T# h4 y/ }( N) G$ b20.D
0 C+ \; u/ \; Y! ?- T6 ]. b+ }5 c9 T5 G" @
8 \3 J/ Y, `* a7 h! ^
* f) D/ J* E1 w% T" L2 s答案详解
- e @3 {2 z' C! v" Q. ~
" @# D8 [( T1 }3 u7 g0 X1.类是对象的蓝图(对象是类的实例)。& M7 I* z9 S# i0 p
3 N! G, c# x5 b0 k2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。7 T8 W( G: Z7 m0 c1 D C
5 W" v8 s3 K& U4 V0 n6 j) B
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
% A% v$ q$ l$ ~
1 Y, U' \! E0 _' s1 W. P+ [9 Z4.单件模式可以限制一个类被实例化的次数。' p' v" J2 Q' W$ n; Z U: _+ F, I
9 {( k0 ]! _) x. R
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。! o c5 |8 V7 d2 [
# ~' D" c, `6 {2 Q6 o+ z* j6 ]8 o
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。4 B2 Z" `- g( V7 Q* a1 d" f
2 I# [' m3 ?4 l/ Q
7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。# H9 s" X; k7 U. C5 G; E" ^
! A; Q. F( v6 ~6 h o
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
) V% m ^' v) {* M( a0 @+ o1 R% d- w
- q6 v/ q$ p! y% l0 U8 W9.PHP4中没有题目选项里所列的任何一个概念。答案是D。& Z1 Y z/ N3 O9 i
; C9 G) H- S" _5 ~5 T+ W+ M* K
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
1 @0 C! N% O7 M+ [- p
: |5 t. g4 p Q- W% [11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。+ H, J0 S6 a- K& ]7 a# {% e
2 |' K% q& M# C" j4 O12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。- f" f- R$ V9 v' i9 s
; S) D# Q+ Q2 [: w$ U13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。6 G& F1 \. \" Z1 _/ v: e
) G% ?# y- s) b+ C
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。0 J, {8 m* }) z3 q$ {. M
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:# E8 b$ m! o( `! i
function reduce_fraction(&$fraction)0 f* U; Z4 H1 u( T
答案是D。
, M, }' p( s+ T/ L% `' ?* H- k0 W. d d$ Y! h, J
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。+ G2 g, ~. _! \0 M1 ^
2 S r1 ]3 D) e5 s16.没有。PHP4只允许声明静态函数变量,没有静态类变量。4 F' z& X' _& t& B y
6 y8 p6 J9 `0 k& e/ n' ^8 A17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
3 w, `% |- z- `" _% A7 R- ^1 a
3 F0 |! |2 ^5 N7 c9 G! I( q; R18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
0 w, K. R& ^) P t9 v7 \
0 q8 P# [9 n) ^2 h/ {# m19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
% p6 S1 K' L! _" t! C8 u8 E: f. C
5 h! A9 g" y, }& v6 J7 S' w20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|