  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14247
- 金币
- 2414
- 威望
- 1647
- 贡献
- 1362
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
8 A+ A- G- f6 DPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
2 V V6 N6 Z* Q0 w8 h( a" e本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。
2 X; ?2 f3 L2 z! Y J* B8 B" C, T& g" L) {+ I
问题
2 Y" H% I- k; E8 N; D$ |6 c Q1 w, f- b, q" z* u# U
1.对象的蓝图是什么?- k. j U: s% e0 u6 V
- m1 M Z( V" ?8 h) R+ R" n0 q答案:____________
$ F5 k; `% S l1 m5 M& N+ |1 S
+ i9 |5 b) a9 F7 c3 V& p/ Z7 _) G/ I' }% w7 \ {% S
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
# \/ P4 F# J4 O: n8 f, Q' v' QB.b- w2 U }5 @- V
C.a
* K2 \ A- F) y3 F' q SD.d! e( U2 A; M. t7 C" _& P2 ^& o
E.e
: Z# E4 R; A! ]1 x/ i4 N
+ r' K: g6 X, s( d, {. _8 w o& s+ [* `9 J
3.如何让类中的某些方法无法在类的外部被访问?6 i; Q5 }* c) Q( m9 U1 _6 h5 G0 p
6 b: p0 k2 n: T, ^$ L
A.把类声明为private
+ ~' ^9 A% N5 fB.把方法声明为private& v0 O( J% B; p
C.无法实现, z, H% e/ E$ {* [( E% k$ z
D.编写合适的重载方法(overloading method)8 ~9 r' }( Y% p( F: l
f* x1 t7 D6 t, {
9 w9 {& l- z1 U3 g2 e, V4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
5 @' Q: A& F h2 w3 ?( Q
9 e7 x0 w( |# S5 v, }A.MVC模式
0 ?: m' z/ T) i1 Y. n; D' bB.抽象工厂模式(Abstract factory)
: c6 i! C8 t @# w9 ^8 r* F. QC.单件模式(Singleton)
* u. R$ {2 k, tD.代理模式(Proxy)" }5 d) z! l2 d3 u5 F E% H
E.状态模式(State)
0 w- Z) E9 l3 ?6 D8 L
) s' q6 f9 l% x/ q& w2 P, a7 ], X0 ~) K1 h3 p2 o) d' ]
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
- t) E: q6 F/ D: e6 [
/ W1 f2 b' X; J3 b# m) ~A.1个
. b/ r) O5 V2 RB.2个
. y$ v$ Q' ^6 ?! R& t9 c* `C.取决于系统资源2 v6 s/ F) h/ p) V! L! x, n& \( u
D.3个. q4 e- R C t# r+ r
E.想要几个有几个 N6 c- v* H- Z, [; o8 Y% n% }- ]
& P3 Z3 b/ _7 D o8 M% m
3 Z8 p: L" o4 Y1 M# q$ m% @' ]2 V6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承$ I" W+ J `5 I- V- q
B.接口
d# x3 y" I0 i) [# I1 oC.抽象方法0 v* l. v# ]* s# M# i
D.Private方法
# c' @. I( C3 ME.函数重载(function overloading)% J, g: V, z5 a- }" p: ~$ ^) O
( d/ F* D; t; \! \( q1 \
3 L/ w p: V2 j' N0 }7.假设定义了一个testclass类,它的构造函数的函数名是什么?
; S! Y5 D4 F% C2 l1 Y* r6 V! ~' P1 `' L2 y/ w0 D. Y1 p
A.__construct
$ b* q2 y" o' k5 ZB.initialize- \6 h' j: b" |3 [1 ]" o0 J: P
C.testclass
* K- S! ]* L0 F' gD.__testclass; o; f9 c( A5 @
E.只有PHP5才支持构造函数3 u2 ]+ l) O7 |, t
7 P2 T7 z( n7 i5 E
7 k$ P8 ?5 M) U8.一个类如何覆盖默认的序列化机制?
' l) J! [4 F! {& e- k: [$ C/ e1 c2 h8 M1 Q, o
A.使用__shutdown和__startup方法7 |, u# `+ H' g3 Z
B.调用register_shutdown_function()函数
4 g0 m' e ]9 |& VC.使用__sleep()和__wakeup()方法. v& E3 k1 r0 _7 h1 t! h
D.无法覆盖默认序列化机制/ i c4 r6 P" @; H% P. g3 K
E.使用ob_start()将类放入输出缓冲中
0 F7 b* d) y/ X' A/ a" X! L8 v* n$ X% M4 f9 f- K
7 q8 |* ~* c; H' U. ]2 Z0 R9.以下哪些面向对象的概念无法在PHP4中实现?6 J4 M" A4 H. b
( i) t" c2 i" m$ f1 \ o
@抽象类
! v" {- c* X$ O, F6 z@Final类6 T! V; B2 f! Y& m' S3 V3 `( v
@Public、private、protected(PPP)方法; U: H& O0 T( d0 i/ a2 }
@接口& e- [' a( d) ^( w# {+ v
, i1 o. V8 J( m3 g$ R1 m
A.抽象类
4 e& e; f: G+ b1 ~B.PPP方法1 T9 ]! Q! R& K6 w( \
C.PPP方法和接口
1 h) `& ^, E3 y) Y! y) YD.以上所有都不可用
4 I% M2 z; K" t7 f( m7 j8 tE.以上所有都可用
$ q1 Y; _. ]2 [% L' @
+ I/ C" P' ~6 d+ j# E3 ]3 D) K0 \ {; r$ H5 V- ^' b( _/ y0 v
10.如何在类的内部调用mymethod方法?
' A! c V# }, |. D, t
; P( M" P6 l6 p: U5 Q gA.$self=>mymethod();# D& l0 ^& _4 I. I% ]7 F/ r' X
B.$this->mymethod();
# ~- S1 G5 M: oC.$current->mymethod();
, Y+ ? z9 G3 S0 o2 N$ JD.$this::mymethod()
5 [$ A, {% W* T+ o5 e2 ^" ?- \% `E.以上都不对1 a& H+ s) } C3 W* T7 U
% c5 X7 z- l1 _/ A
# w$ t- `4 t+ @: o0 p
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+ ?: Y. w- v1 w
B.Null1 O+ L1 `& e: k
C.Empty, F# k+ w0 L3 W/ u. {
D.什么都没有+ i, } F& s: z! D
E.一个错误' d5 m4 R. c, p* h+ z' w& ~1 Y+ y
) n8 b v+ U% l. R6 t2 q
! S- \5 E: u8 I* ^& @
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. U d3 I: b/ l0 S: V; v
B.5
8 c7 r: U; _; [! N0 v+ dC.2$ }' P' Q1 o R/ Z+ s# r
D.Null: i; d) {# [5 Y( n
E.什么都没有
( G6 v4 m( B" B2 E! E- ]9 B- T' U+ t
5 I. I6 D" k6 [" j$ m
3 ~! p: R% p" [8 S4 D; O3 L13.以下脚本输出什么?-
- <?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
9 f+ }; t# D$ Z+ f) [B.10( }8 d6 p* U6 ^) R9 D9 i
C.什么都没有8 H+ F) A0 m- f
D.构造函数将报错7 W/ n; D0 X! b6 \% C
E.510
' }1 V- Y3 p ^- ^* k& Z3 J8 k
9 P) x9 R8 x0 [" o
* ^) S3 X4 G! k14.考虑如下一段代码,执行时,$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函数必须返回一个值
/ }! [1 `2 k: }% w" ]B.reduce_fraction函数必须接受一个整型值, i' n1 ?9 p! H5 `
C.gcd函数有问题
( Q# _' N; S5 G! gD.必须通过引用的方式传递$eight_tenths对象
: {6 F% q: f/ w5 O0 [. jE.对象的实例不能传递给方法以外的其他结构。1 N+ X+ _/ P6 Y1 {" g
! K3 N$ G1 n( I: l5 \% A; ]* u2 `& c3 f
15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法; S& @, t0 t4 x0 P
B.生成myclass的实例并调用mymethod方法3 h( E# f! h6 H# J% e( r
C.产生一个语法错误
3 \: j' v3 S8 [1 ]D.默认myclass类最后被创建出的实例并调用mymethod()
3 ]1 `9 J& E& n. w4 aE.调用名为myclass::mymethod()的函数8 _0 P0 Z {1 W+ ~/ N' g
! p9 y4 g. e4 k3 C. V r; c4 c/ {1 {8 x( S6 ^* ?
16.PHP中有静态类变量吗?* F" j$ \$ \2 Y. m7 d
, h4 N- Z: F* \" F. G" f1 _A.有6 Z4 [3 k( I$ N: N( K
B.没有
3 U: G. o( m/ h. r- y2 f" L+ c- G2 x& Q
% t1 R5 \$ C* F* I17.以下脚本输出什么?-
- <?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
) w8 f1 M$ i* v* rB.2- D. V7 I! |6 J
C.一个错误,因为没有定义a::$myvar
4 T E( E& D1 R( i) `" h! BD.一个警告,因为没有定义a::$myvar
. D7 d: P: S" {: d8 ?E.什么都没有* V% ?8 ?* Y; x6 y! ~ M+ T
3 f/ h' o0 _2 T9 ?4 y" j
+ v$ i1 O! e' I! r18.如何即时加载一个类?+ k' V8 _, H. b! H1 y; m
+ V, @, n- M; j9 ]+ aA.使用__autoload魔术函数) R8 z+ P- c* Y5 M7 A: _
B.把它们定义为forward类7 D: {) L# H" u: E0 p
C.实现一个特殊的错误处理手段
* A! l! a$ S1 d: U& N1 `D.不可能0 @5 `, ~3 g$ z& K6 F9 u
E.用有条件限制的include来包含它们
$ ]% |* y8 P' J
1 V: p2 I2 P2 U5 e
7 o) @3 m5 V* I! U# V6 K$ n19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?% ] U4 r! D5 `
7 p; O r4 M x0 N5 `
答案:__________' { L7 N+ c6 E8 U
8 L3 N5 M0 Z- ^) p$ R( h- F
+ C; n! B+ l0 o3 q$ ?6 U3 L20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called; V: J% Z5 m' |
B.一个错误
. N# N# o. @" z! V+ x) Y6 jC.一个警告
5 j+ w# j; F7 F1 ^ ^; |D.什么都没有 O0 C5 k7 A _: h- S8 _- @
# x0 Q/ e0 O7 z6 r4 Z- K$ |+ ^
8 O( h7 |1 ^' S, t" l6 @) r! { D1 c; ~+ ^
答案速查
3 w6 T! a1 ~, d, |1.类
& g- p* P1 n9 {8 t' n! h2.BCD' ] P; ?2 n |5 a" R8 i
3.C
- b, l0 `& D0 ?8 E8 b4.C
( v: h l- r7 l! ]5.A
& v! R8 W9 m; w! u& q- P9 q1 t6.C
0 x2 b! C% n# n* \7 K5 m- i7.C# f0 }% j" P8 \8 e
8.C
; j, ]2 c) {2 S. Y" @; f* B/ x9.D% z. R0 M" x! g' }
10.B
% p, P+ L" S% [8 E: X1 x* Z8 ?! ~' j% z11.D
5 C8 h* {) p/ `. J! R7 y12.B$ r$ M1 `0 n6 u7 ?" X
13.A
8 @8 Y7 g8 W( O14.D
2 m& d2 ?* v, U! R15.A
' v0 w/ ~: A) A0 [. l16.B
; @/ N) X$ H _' X# o17.A
+ p0 l w; }: m) w: D# M18.D' O, C) d- _/ Q: f( M G
19.设计模式5 H' Z' V5 \5 K& `- m: \
20.D
" L3 A1 z0 ~& S( R, W+ K$ d/ o( p2 _% ^+ J! [) [3 e# p3 H5 v. I
4 }" H3 L' M+ [3 r, T" x( E# v5 `. k+ B. q/ j2 t
答案详解7 p2 a: [5 h$ ~. x5 e
" Q% l" A$ X$ l7 A7 Z- `
1.类是对象的蓝图(对象是类的实例)。2 f' ]* P/ ?" X
" ]6 }+ @; l& z6 ]+ w0 h* H2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。. M- P9 ~4 ] d6 V$ B0 D
$ n/ v3 c3 s% s2 a$ T: @3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
9 j* K5 o) c f5 G9 V4 \
' G- N" _5 b2 w# n1 T4.单件模式可以限制一个类被实例化的次数。* `6 s: S; T1 k2 d2 n3 n+ L
& i+ H6 k; w8 ]$ W. R" d
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。
- z2 q8 ^3 Z: ?+ k" q
; Z0 w! @* ]& ?& M. N2 C6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。& P; u) W- O0 @2 L1 W' A& o, Q" Q
' [8 d) i4 A( {8 E' {: p7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
' t5 Y: Y w3 ^( G) u( [
5 Q7 m+ u% D! j; i' I: H8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。& N" V$ O* i# a7 t
7 Z' J5 B( c. a9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
4 K+ W5 V0 q" k& N2 a$ K: F8 p8 I. W8 _7 T! W
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。: _& E; u( p' j/ Z5 g! g+ l- a
9 ]1 S2 L0 p/ v& \" h: K
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
! [% [4 N) j& O& }. b
+ ?3 o' ]/ \6 t; ?12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。
3 u- X' `5 R. H' P
! Q5 n% Z4 d& e3 C" Z13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。) v9 ?( L; _5 s5 F
( I3 b& a: z3 V! T! `% v14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。0 j6 x5 y0 ]6 o9 t5 ?) [* M
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:# ]: C% u, X+ l' O. a
function reduce_fraction(&$fraction)
! v: a: m, k! ^, S答案是D。, E0 O' t6 H+ }8 e# B
7 W4 n# c0 x4 q( |
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。, T% e' ?, X' h: v
& n9 i% b Z7 h# O! ^6 E16.没有。PHP4只允许声明静态函数变量,没有静态类变量。: |6 `/ z& O( b9 M2 _1 L
7 J* F; ^/ B! j
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。! r/ T& o/ V C' G% O% a
3 ]6 h% b( F6 Q$ e# s$ w5 s. l
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。 ~0 C, L. t: w; N8 ?# I0 y+ L1 |' D h
: V+ X }9 [" A
19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
E% e8 a" c4 H1 L$ R
* ]- }8 s1 e3 b! ^% o% [4 F20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|