  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14249
- 金币
- 2415
- 威望
- 1647
- 贡献
- 1363
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。8 Q6 N9 ^7 s; S) K2 s9 [! \3 f
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。1 v8 A0 v0 {9 p( w( ]/ u8 L
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。( [* m9 v$ C& W* e
! J" F2 ~ @$ C+ ~: x% a
问题. ]& Q' h; V* G$ p" F" d h
" K$ J+ x' L3 f8 U2 K; N7 x* Z1.对象的蓝图是什么?
. Q5 S: X* T1 s- g9 Q
4 C: V( K1 K# i7 A8 X8 }答案:____________
3 e' L. X/ T9 K/ b! {
# V& h7 A8 V/ l+ j' M6 o+ @( v. X$ D3 V& Y5 _
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% c# f. G! t# N z# x4 s
B.b; j$ A, p$ M* G/ C' W
C.a: U3 H7 O# K! f3 Q/ c. E7 S7 u2 T' \
D.d
1 {* i$ v9 I9 c' k% v1 KE.e/ [9 j" n. N2 r) ^, a! |& c0 U
+ ^- }/ P- ~& C/ W5 f8 M! e2 x
! K0 r z4 K1 {3 P' q5 L/ l3.如何让类中的某些方法无法在类的外部被访问?
8 A+ X3 i+ ~5 U5 N7 M5 [
8 n. O# L1 j1 x* L" n% xA.把类声明为private
, a T. ]$ t9 p' i5 o0 _B.把方法声明为private
" @0 v# _* {# R+ F$ |' m+ OC.无法实现
: k! ?2 U4 J+ ]" FD.编写合适的重载方法(overloading method)( G4 H& \* _! [4 V( r
% v* Z2 p9 E. q* Y4 L* _5 b, `) J6 a! W' Y# P& U; Q# n! S2 {$ n+ U* ]
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
% m( q- [0 [ j8 c) ^1 U0 U C
0 B7 j- U6 K0 ~% N/ T( B' d4 h9 [A.MVC模式* A5 ~4 i" L8 F7 z" i
B.抽象工厂模式(Abstract factory)1 U) a: K$ [( ]8 f, i# R
C.单件模式(Singleton)
) ]! X# s) M% p+ \/ rD.代理模式(Proxy)5 D; q7 h+ ^/ F9 ^
E.状态模式(State)
4 c0 B7 T" E' _ b( Z* ^4 C* U0 Y8 R2 O
: i( q, w& i& b5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
) z$ W1 T, [# A) e/ J8 S( V3 h, U5 V9 L
A.1个* N9 X; r$ W' h* m
B.2个4 G- F, h/ G- q0 M" e( S, X3 y
C.取决于系统资源
! ]( I+ J0 ~9 d, wD.3个' ~: U4 Q$ E3 }! H2 L' N) H, S
E.想要几个有几个
p# Q% F0 p6 P$ p; J/ I* x( Q$ `8 ]& w9 u# t& l
# T( F. s1 i* }. b6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承& {% F# P& d3 I4 F H$ f4 ?# k% m
B.接口
; K2 `0 i+ L1 L" y$ A) o- ~: OC.抽象方法' E3 \6 p, F5 _& C& t9 _
D.Private方法- ~0 \4 K* g" O
E.函数重载(function overloading)) W4 O. a1 g4 G& _& o
2 |( \6 B7 t5 Y; B8 G- S5 L M, n
5 C; G2 @* s, I
7.假设定义了一个testclass类,它的构造函数的函数名是什么?
- k7 `" z! [4 f* `' Z9 E
4 R8 {" W9 |8 ^4 h. hA.__construct1 | h3 c4 p9 d
B.initialize2 D4 W8 I* l2 t+ R/ K
C.testclass
0 G! H0 B3 M: F8 X4 H6 OD.__testclass4 Y" L- O* C0 ~5 d& `
E.只有PHP5才支持构造函数
, @# h6 G, i5 F& t- y( l, i* N" J
) T. f- L6 Y/ A1 {
8 u9 E& s) G9 \- _, W8.一个类如何覆盖默认的序列化机制?
o# @5 l0 V/ ~, Y6 W9 j' @! w3 a+ H0 v. j- r4 O- |! Q
A.使用__shutdown和__startup方法
5 _/ s: J, n9 t+ H+ j) j5 T: JB.调用register_shutdown_function()函数
# U$ H1 f* u! ^1 ~" k; H/ yC.使用__sleep()和__wakeup()方法! K- n/ L4 h9 X; G8 c# d7 S+ z
D.无法覆盖默认序列化机制! f. P, E' H" R" o( M8 [3 d5 {
E.使用ob_start()将类放入输出缓冲中
# O1 X; g# a' y# H, B! j: { c: f( @6 E$ K+ |: g' l
, R1 S( p ~0 M& r8 Q- [( L8 R
9.以下哪些面向对象的概念无法在PHP4中实现? l, k# h# d' x# @$ T# d" E3 J
$ w [, |1 X; s3 w
@抽象类
3 Z; R6 S$ W; l1 ?3 {5 {: c. K! I@Final类+ k8 a; n7 ~( S# H9 ~0 L
@Public、private、protected(PPP)方法
/ G# m3 W0 z4 z) k k8 g@接口
6 O) c* y& B2 P
V K6 I2 T! b+ l$ u& IA.抽象类. m/ d' }0 }6 k
B.PPP方法
& U# j! \2 X' W1 ~( KC.PPP方法和接口, g- x! t: z$ K0 D
D.以上所有都不可用
' e5 s- G4 S2 ?. _E.以上所有都可用
. ^* F. s, [8 d5 _( Z( T7 u; s! D! h8 L0 t+ F' ]- G! g( ^
8 V0 {# d0 H# S/ U
10.如何在类的内部调用mymethod方法?1 V% a" d* L9 c8 y8 w1 ^" `$ ?7 q
4 i5 Z0 _; K' P$ W- x a' n
A.$self=>mymethod();4 J2 y* j2 z$ D1 N
B.$this->mymethod();
$ ~) F0 W& S2 N$ o6 z/ ^& OC.$current->mymethod();
5 q$ C G: P# _D.$this::mymethod()
, b6 ?& R, E" ~/ mE.以上都不对
6 B! }. B. d9 p& _
& o# f8 x; a* f! m" J- J) K+ u9 G0 f4 G3 |$ g
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* A* d$ g3 _$ _* j/ m4 m* P
B.Null
& y+ J: b) |- m6 Y2 R3 mC.Empty
8 @6 R- m+ t% B: C: \D.什么都没有
8 p& X- n$ f, q/ @3 _' ]E.一个错误6 _! i* ^" R5 `: H$ X; w0 i) d( _/ \
) f% A; G, C% ?( A# ?; t0 _
+ z: ?$ v7 t8 \+ o: k
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
5 ~# a+ t- l3 P# Z. E; X- hB.53 ^( \& T k# L
C.2
" h w Z$ R9 S, ED.Null) u. o$ d# P& A; l& d' K4 C
E.什么都没有
. A1 M( f/ @" j9 A* q1 }' v, P: ~; [6 i* u5 I
' ?. j% d8 V, V# ^7 u5 o
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. O7 n A, ]9 R1 k( o: q! d( ~
B.10
6 k5 }4 R5 m1 C. y) }! T. c* ZC.什么都没有 _ [& L4 P3 O2 g3 d s. [
D.构造函数将报错& m0 K" F0 C- P( x( Q" A% \
E.510
% u* U2 `$ j; {* Y7 k
. a9 p$ L, a" E0 ^+ I2 E( z% z7 f# S( }. @/ y% s% i
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函数必须返回一个值% I2 C" ?6 g. Y- F
B.reduce_fraction函数必须接受一个整型值& M9 {) _- q9 c# P* L
C.gcd函数有问题8 a( x7 @& R z5 a3 L" {0 k
D.必须通过引用的方式传递$eight_tenths对象
8 p4 v) X" B$ z" v* eE.对象的实例不能传递给方法以外的其他结构。
8 @1 V6 t# h! }) x* L
+ R& P, N( f" t3 s* D! S+ D% J$ o& h& j, V0 h1 r1 d% @0 J
15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法* A& t, v4 o% d! ]# t
B.生成myclass的实例并调用mymethod方法
, ]0 n: P+ k& {! B) aC.产生一个语法错误
2 z% ~( `) l9 q5 E+ _D.默认myclass类最后被创建出的实例并调用mymethod()1 d! K- Y. t3 }6 ?
E.调用名为myclass::mymethod()的函数$ w6 ^- o( M4 |
, z6 L7 T4 A/ U' J0 Z0 ]$ C' B
9 `2 T0 m# ?, k% k( \$ I16.PHP中有静态类变量吗?
: d: g8 w2 v% A2 _2 P* Q# P6 W1 I3 {, T9 E
A.有
3 D0 p/ j \. b' r, cB.没有
, C& T3 B. |. K7 t) z
& v8 d, z! r+ @4 ]3 Q7 T/ r- N4 H! D; F) ~& {3 B& v: q
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* C$ ^- k6 E. D6 S0 W, t0 a
B.2
5 I3 {9 J$ q8 `: j2 d- q" Y$ pC.一个错误,因为没有定义a::$myvar
4 r! t3 T0 j0 A; o% A4 kD.一个警告,因为没有定义a::$myvar0 b: E I3 T+ R' V- d( {1 k
E.什么都没有
2 N1 h) _$ \- \1 a5 J" Y R& l) c7 U4 y' q
9 d2 @) Q) j9 F* ]# d! H! { Z18.如何即时加载一个类?# k# q* Q9 \, C+ x" I$ K. F
D- c' W% P+ e8 q% z. M, f
A.使用__autoload魔术函数
6 p7 O4 f+ h( k/ M& V# kB.把它们定义为forward类( ~7 L& r) \6 ?( w) \) k) V
C.实现一个特殊的错误处理手段$ L7 m+ k8 q/ \% @/ k
D.不可能8 k! g( \$ ^% \- d) g' \
E.用有条件限制的include来包含它们
/ t+ N0 |5 P9 b: T5 u/ n* W( r# X
$ u6 x1 O2 f: {
* j8 x ?) r* b9 m) G2 R3 K v% O19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
. _6 x2 W; q0 F
& @) X. |- Q* h5 }$ e6 C- K 答案:__________4 S& o2 p" H( W) g6 ^
1 Z- P* X+ T# R- S/ U! Q$ Z
8 E- q1 o. `/ B7 X) y& x0 ]/ U) _20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called
- k+ V6 e: s. @* c8 LB.一个错误6 c, N5 S( g9 Y: h, [, e
C.一个警告
/ t% Q& g0 {3 J+ F& MD.什么都没有
6 d% k+ q6 j. A
# w- A( a' b% e; \- y& E: S: ^
# n2 K+ E9 [! A' Q) _+ a& f
4 f1 X7 a$ c/ d9 J4 K. p0 R% A( m$ w$ ^答案速查4 }/ @( ]) Q) u/ q1 o& m3 h T* o
1.类
[+ j3 n. [) [3 o% D: W2.BCD `- u, R% u) ]; }: [. f" _1 E- l
3.C
# y$ y. t( D- i: a g9 Q4.C
" B/ h; q4 H, ?, n6 E5.A |. X' v( J5 r4 s2 z: I
6.C
: P; e" E& h5 I Y# X7.C
W; l; k/ p$ s; z% E. l8.C
2 T& O# T6 y, u8 g) ]9.D
+ R8 ^$ l' I# x/ o# p$ p10.B/ A" v0 N* x& y# |; l6 {4 N
11.D n" N6 L9 {8 B. s- h6 o
12.B
0 Z( \( U5 j- {) n13.A
6 _) L* X( |, h/ |7 o! X14.D
$ @" r' t1 _6 ]4 ], ]/ x15.A
, w0 U5 r# `7 Q5 W+ X16.B
3 Z% c' V) g& p$ L3 \$ t3 r6 a17.A2 L3 V$ l8 K% L2 }3 o9 e- z: M( |) ]
18.D& }! h# q+ W7 U2 A! x% ~
19.设计模式7 g( d, W( i' c6 I) |
20.D- D4 i( o2 p; m. A8 b" I2 F% i: S
) v* H7 D; s: a$ q
/ f0 z b! {/ j+ }9 @& F( U6 s4 N# V" m$ T) [: g7 T: }
答案详解
7 L" T# A& R# C! d
# l J1 r4 e w5 D" @1.类是对象的蓝图(对象是类的实例)。
: [$ ^$ Y* K y2 ]6 ^/ n1 J1 P& \0 ]8 o: h/ y1 R
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。9 H% d6 G. X* K m e) q& j; s
9 Z% V1 M5 U) i% ?3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
% v9 M3 `* ^0 v G" g0 _" i" Y4 }' r/ h V9 C
4.单件模式可以限制一个类被实例化的次数。. K w' w. z! n; \- a
- |7 t3 V" z2 k G* M& l' M4 i5 c
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。 K' k/ z5 R/ e E
: \5 _7 E7 n6 k/ _- F& V
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。" B4 w; g9 X0 @9 t
. H5 Z- K) ]5 j) r; Q7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。( z. h/ W, O. f
4 ?8 U" D \+ S6 |) Y! b' S- t
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
0 ]1 J$ X$ k- q$ R% G& q8 m+ E' u ~' v* {
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
; K0 e" I/ c; T9 O6 V* l' B4 O& Z7 C+ ]+ n- q* k. n9 a
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
: S$ Q; f, z9 [5 S9 `* _, ?: c3 l- U! n' k c, J; n
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
* u }/ e, z" l8 n5 w( j' a. p! N. k" J" K( N& d
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。3 q; x+ F; Z u. F9 \1 r, P; R
; I k! t4 P& `
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
- M0 z7 f7 x* D! t8 ~
+ t" u0 Y* T* `+ Y1 y7 W14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。
$ x s. V O% h9 w- \: Z# j回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:- _4 q7 h' [/ p g" Y( Y; ?
function reduce_fraction(&$fraction)
5 _4 D/ m9 {+ I, i3 J# \( ]6 U3 z' |答案是D。$ c) ?" |7 Q& v1 Y( y- [9 i! Q; o# m
! N0 S8 f0 i5 m% u# K+ M! z! j9 o
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
( e7 K; k: o( S) M' }5 n4 u0 L% f2 O/ \) Q- V
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。 Z: W a D5 X+ J* W9 ?! ?. Y
8 v+ U$ X. d1 s' u5 m
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
! |9 V% C6 C* F# `6 i& @$ N, i2 n1 ]5 B4 } v+ P
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
5 J: T s6 z) {2 X' L v, o
- F6 N3 o) n) V3 r5 Z4 z19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
, m3 Y6 n' k! s, j6 m" | e) i
% N& J6 R* B: L% [' c20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|