|
  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14341
- 金币
- 2456
- 威望
- 1647
- 贡献
- 1404
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。1 F- }- Z, L% E( S5 ]
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
+ G! t& V& o- M( P8 r7 o% x本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。5 [; k$ V3 \4 S7 N2 j9 O, H' Z
/ X8 s: N/ c2 `$ G+ h& B/ I& l9 g% X
问题1 E6 T- P8 n# Q$ e
% A' H z* W* w
1.对象的蓝图是什么?$ F" e9 h$ g7 G j# ?
; Z H# R0 e! t7 V; N: n+ X& V; H/ C4 g- d- y答案:____________9 \5 }7 t& p3 W% u, M
$ u, f0 X1 }5 Z6 a& o [2 N" j% }6 U' v4 b
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' u( k4 J$ o# `( [% i, c% N
B.b' o9 |# f8 U2 [$ B0 p
C.a. g1 P8 O9 l- L: q
D.d- R" V! v+ P$ H0 o' W
E.e, q7 m9 `8 s: z( k6 i) p4 E
+ A* O9 e+ r. }9 K1 B& W2 N5 X$ ?
& C: \, T q% K0 N5 y. Z$ c# S3.如何让类中的某些方法无法在类的外部被访问?
5 A3 t- i9 I1 x( ]% T. ~
I& ^2 a" G- i" _/ n; h6 q7 JA.把类声明为private& f& [) T1 |% Y- c2 F
B.把方法声明为private8 d5 C- F! v, Q& W" d2 d' I: v- e
C.无法实现1 c3 t: s" O: U [& z" C
D.编写合适的重载方法(overloading method)% }/ D3 z/ @0 i$ Z3 |' Q
$ G: @. I; l5 t5 Y) _
$ f% `2 Z$ u6 W$ ^4 x
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?" @0 r- e9 X% L7 y0 g4 O5 f1 Z) b
: m0 w3 [+ x3 G$ e3 L7 ^: l5 C
A.MVC模式
1 J5 K( ^- d' x1 NB.抽象工厂模式(Abstract factory)* B& P4 \. f. k' s: T
C.单件模式(Singleton)
; H9 c% |" v5 {" iD.代理模式(Proxy)4 l9 Z" Q% Q9 u0 l. n; N1 k
E.状态模式(State)
. m- W) [1 f( D) ^8 E& q3 Z A
% O H& b0 I# }- I! T
( J( ? U6 u2 O$ N3 h! n# V) [9 P* q5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?& X( l/ C/ ?; q, T- g4 i T4 Y
3 l2 }3 i5 V y8 cA.1个
2 z4 u% v9 c, i& ?: bB.2个
& g, u' P8 ^+ q- rC.取决于系统资源1 O8 V2 x+ a. q- h7 M
D.3个
6 q# w2 z' K- a! wE.想要几个有几个* a2 `- z1 }- A5 A! ?
4 n# j2 U _% Q/ m% e
2 K# e! ^4 w, Q
6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承* n @' x6 @% V0 D M
B.接口
$ O% n- W$ n! F( K, x/ n5 f# Q: nC.抽象方法1 w( s. A1 l% q
D.Private方法
( S& T+ c G- ~& r3 k$ w" M2 ?E.函数重载(function overloading)
; p& I, S7 h4 K/ `- W3 j
' d) H8 S% L+ F
0 |8 ]' U7 [* G0 |; D7.假设定义了一个testclass类,它的构造函数的函数名是什么?; E \, ?, Z* d5 u' l( Y% o4 f
0 l8 E7 [8 i) Y9 h* lA.__construct
! z) Y- M8 n! T) \2 \- \3 y; hB.initialize+ [+ X' A+ p& d& P G% ~# X8 m1 U
C.testclass
- I1 ^. n* B1 {8 lD.__testclass) b( \! @- \, S4 i! D: ]; ~" o
E.只有PHP5才支持构造函数: H+ y1 U) B$ H3 l1 x' l
9 {+ Q) n$ c2 L1 ]! z2 Q
4 l# _ F* R) V: ~. R- {; W5 [' w
8.一个类如何覆盖默认的序列化机制?
( ` q6 ?! n$ F) Y) t; X
$ X8 k0 p8 c# D: u2 [3 ~A.使用__shutdown和__startup方法
) [7 g" l9 I9 ]! iB.调用register_shutdown_function()函数
( [5 k. n, |# `4 I# t/ k0 Y% C2 r& Y7 JC.使用__sleep()和__wakeup()方法+ F' ~% ~! E& N6 w2 D, g; I5 R
D.无法覆盖默认序列化机制
# W+ P$ ]4 M, d+ Q" v- oE.使用ob_start()将类放入输出缓冲中
4 E. i( k$ K8 ?* k
9 p& }. {" n% ^2 W; L/ E1 b8 u
9.以下哪些面向对象的概念无法在PHP4中实现?
" ?* q! n) D2 K; D3 ^( O- v' {5 }% h: Q' ^
@抽象类
4 }' k, H) w. J$ Z8 I8 z, V/ @@Final类
! w& x N, W, z! o9 v; ~@Public、private、protected(PPP)方法
$ Z# v: q+ l% t7 u@接口
; u L, y% |2 K: T) N# x+ C5 L
/ P; r" k' C/ j' Z. H, u6 x( ~, XA.抽象类" a3 c" a, B' ]3 g' Y& g( X
B.PPP方法
, E5 ]+ L$ A4 y; g1 ZC.PPP方法和接口
! N G2 i( K0 R2 N5 tD.以上所有都不可用
% L$ g+ ?+ }# }( K- GE.以上所有都可用+ T1 @5 D7 P( j* U
0 H+ z% s7 t$ t8 m) S+ C8 _0 ]
M. F0 X1 E, E# t6 p; Z. U6 D10.如何在类的内部调用mymethod方法?; S* w4 T7 Y$ v' H4 L, R9 W5 Y
* g1 ^. T6 O# v8 S
A.$self=>mymethod();
; e' q: }1 U1 j3 _0 LB.$this->mymethod();0 w) u5 G/ w v, P6 K+ J
C.$current->mymethod();2 M* a( p2 c4 z4 j
D.$this::mymethod()9 Y3 A4 u9 x" W! W. |
E.以上都不对
$ r4 ] C; K1 t- \$ H p/ H
0 I$ S, `* l$ W! N0 ?
) N. \$ N' |* G11.以下脚本输出什么?-
- <?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
R" s+ ?7 Q+ g# B2 e- q- uB.Null0 t& i7 c# f1 G- S/ z
C.Empty
; ~& P& x, i% E" V3 jD.什么都没有' x( Y) q! m7 _6 W" N7 J
E.一个错误( `: w3 `6 m1 N/ H, `
& C. @& [' P5 {7 D" D
0 j/ Z, ?3 H" r" _8 V$ n3 Q
12.以下脚本输出什么?-
- <?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, m9 H7 @6 d* v
B.5
9 U5 T; ]$ b* q7 o. e GC.2
( y% f* ~/ |; \" k. qD.Null: N- o% O% ^- y: {4 p- Z! L
E.什么都没有
" C* r8 B5 E' n& Q) W+ ^7 h5 ?; o; ]% U, Y( J" a. a6 W1 r
. [0 ?, l% g2 Z# O% }! G4 C13.以下脚本输出什么?-
- <?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
7 ?- `, O6 ?6 OB.10
4 K: l; j" W+ p* w3 KC.什么都没有
9 | W/ i) H# _7 m& I+ ^3 i8 p4 ~D.构造函数将报错
% e$ T6 L& v! \8 H: iE.5103 b4 o8 Q" R! j* N" ` b1 K
( q m! \* f K( q7 \
4 R& r } P# Z/ [/ ]/ q0 h
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函数必须返回一个值) h1 A& {6 Y) o
B.reduce_fraction函数必须接受一个整型值9 e6 d s2 t y/ v% m9 r
C.gcd函数有问题
9 F" y, l! j: T. e W/ \# T }D.必须通过引用的方式传递$eight_tenths对象
( D& M9 s3 I* _1 Z1 lE.对象的实例不能传递给方法以外的其他结构。
6 B! W- {' ^. ?: p) }
! Y4 F. Y ` s5 e+ ?
4 E" n0 i* I& g \15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法
3 I7 m% i/ |( |0 W) a2 Q1 H$ uB.生成myclass的实例并调用mymethod方法
9 g; s) q, h+ @. a7 ^C.产生一个语法错误
. u$ C/ b9 I6 e( h- f: g! XD.默认myclass类最后被创建出的实例并调用mymethod()
) b# x3 [% u8 n7 R) f8 [E.调用名为myclass::mymethod()的函数
/ G6 j( ~; R* v9 z4 a
0 J# m! I$ W) I$ G) l1 x
l: D& j+ a8 G8 _16.PHP中有静态类变量吗? n1 n2 a. \) ] |2 \- ]
* s0 S% F+ a: P- qA.有
9 B+ a) n# K1 e% k: r% dB.没有
1 x; d6 v( y" C6 ~/ f2 x7 \: u4 N# Z5 M, Y
+ f9 z9 B5 }4 T$ h- Z
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 N; w" Y! |8 Z/ [: o
B.2
, s8 J; }8 F# a$ E- K2 ?C.一个错误,因为没有定义a::$myvar1 s3 S- D1 Q1 X4 c% F) N/ a+ b
D.一个警告,因为没有定义a::$myvar
/ u5 W; p/ w" A1 p! D: XE.什么都没有
- n2 @1 M! c% j
3 h3 S& a0 X" ?& K+ s' P c' g
. ?* Q! p3 E1 y, W18.如何即时加载一个类?
: T6 ]' T2 A! } m
! e9 f4 v: u/ u+ b: K1 r0 q, kA.使用__autoload魔术函数' i( w3 [$ W* a, d% A
B.把它们定义为forward类, O9 i! r8 C* \5 K
C.实现一个特殊的错误处理手段
6 j9 @1 I) S/ J: S+ [# u( fD.不可能
9 z# `% \6 m o9 CE.用有条件限制的include来包含它们
9 N0 |4 }) G. ~% O3 G; y) e1 q: |
8 S/ |8 r5 z+ A7 H7 T19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?$ I1 |; [- O+ _" s7 ]
- a* ^8 t/ G% L" l* T3 n6 d# E. y9 ^- M
答案:__________
' L. k' K& g( {& O% ?, l$ P& F
7 U: N: F) O7 a" ~! B. {) h( L20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called* }6 {# D/ v% o1 Z0 h
B.一个错误
4 H: D& O/ Q C/ U* Y) k) o& EC.一个警告- G, u# Y) O3 H( R/ K3 B9 l* q, R
D.什么都没有% M3 F1 P: }4 x- d9 b
' L) U4 C- @, |! p4 L) B. y2 E
2 {, I/ w1 l% Q4 j n+ W& y9 v
答案速查; R* l! H6 Y! g
1.类: d I3 e- s1 g9 L4 Q5 l2 U
2.BCD
, x$ U \( b w, T5 k3.C
$ S6 t9 k2 f2 \2 h: Q$ ^4.C
1 R W: F6 J: H# k0 E+ I* Y5.A# e; j1 Q% t6 \2 C( J5 `; `( r
6.C
' l: e4 u% W5 p7 z% ?/ U7.C- @' r' O+ A) J2 m: k
8.C! r m5 n* \# M/ \ `
9.D/ Z- P' s4 @& P) H; E8 S0 ?6 r* d
10.B' s! [' w% H: v/ |. n
11.D
; Z: o$ v& c: F; R: t1 [12.B, m' [; Z) N+ K; U6 m, _
13.A) c. V& U) w7 x, R
14.D
& Z0 q6 J7 H& A! r2 m15.A/ P5 W# X6 I" x' l `- k1 I
16.B
$ ?! u3 {. j* _+ f' q. p! p4 J# m5 ^17.A. k( z( w" s( m _
18.D8 _( G S8 }5 w8 k
19.设计模式
5 _0 h0 _8 e6 h20.D: ]6 D" Z( V; k( {$ e
% j m c* z, m/ ?# o5 Y3 F7 M
5 G# |, J# G, N2 y
* k/ l% | f, ?0 b8 u8 G2 ?3 u" s
答案详解
% R0 D, I* o: r: ~+ G3 T$ M5 n3 _6 k+ z4 c [1 d7 U
1.类是对象的蓝图(对象是类的实例)。& l1 p$ F0 i: x! r* I' {
1 `) E8 z e% ?5 u9 k2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。
4 X; r1 H* \6 i! t; m# Y$ t; {0 i$ V/ l0 v5 s! C! {- T) s+ Y
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
g0 b! `8 g" U) U
3 g; d# f6 i. k' d5 [4.单件模式可以限制一个类被实例化的次数。4 w% R" f8 r- z; d
! ^" k! b' t! `# C v: R6 m, I, k0 c
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。! h; `% p4 R' F) u) } C
, j2 i# w1 [( l3 W9 b6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。3 ^- C( ?5 R3 h$ z
( p+ f+ u. s7 T3 ^" ^7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。. l9 ]+ T6 {4 w1 N2 _
# N6 J `* t& I! [9 U; v9 E
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
( j, T/ c: x1 A/ C
3 j1 S, e# W7 C5 @; W9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
3 V" T6 [3 [) f x% ~% q
% f0 C0 A6 q Z10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
5 _, v3 r }- b% Q
- j3 Y. A! w) p11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
2 {# ?# N" X. E! f
# f2 b z$ h" _2 O* Z5 i12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
3 \& g% B) `) L) g# Y/ Y, `/ M
* K' {' U8 `& u; Y13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
. K) g+ H! U( [/ B4 v( ], [
* ]5 L ?# O+ Z% x8 [, m14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
7 |) A: v+ u: Q8 Y# u5 Q. z回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
. z3 \2 G# L$ R( ^0 ?* J q function reduce_fraction(&$fraction)
, h' W$ M5 r$ G1 o答案是D。
1 b" D1 w, w L8 }9 {1 s6 y( D
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。& ^6 u5 }8 f3 O$ D( \
7 b2 Q; e, l# o, S4 a( d16.没有。PHP4只允许声明静态函数变量,没有静态类变量。, t* l4 R' Y [6 @
) x! o7 w# f- m; \5 E
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
- V- b, b8 j) B E: E. ~0 J' y) b/ _1 Y- D* z) C
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。7 T3 o: { l+ J/ f6 w6 E. G: K
* y+ n2 X- E) D" t7 c9 U19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。. k7 O) J/ X" p7 [
' ]% @% |# U: v/ V
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|