|
  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14391
- 金币
- 2481
- 威望
- 1647
- 贡献
- 1429
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。1 V% k0 i. \5 [8 p, D( }0 t
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。$ c2 P+ n4 H0 A6 R
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。3 W1 d, }/ n3 Q; Z6 V+ `& z! x
7 s/ x& A5 z) w. Y9 K5 L
问题1 ^/ P+ h# ]! y+ {5 R) }5 K4 T
7 G d o# { S: U# b8 R/ `( a h
1.对象的蓝图是什么?; n/ i* Q& K5 \+ S+ J
& T: q5 m+ D" R! z( q0 x ~. Z
答案:____________" T x6 x% P. m( g" Q" {4 q# ^
, |/ i7 [! i% V: M
+ ^& s/ y4 o. I2.以下代码执行后,数组$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
o8 { p* ~; h+ O4 K* c- LB.b
$ {- T) W3 @& x7 {C.a
. s% e( ^; V2 f4 B0 ~) [D.d, G$ x3 T7 K5 g% Z% t; w6 ^
E.e
1 H% W$ G+ u7 r3 }
7 k1 u& r" m7 q$ v' i; Q# c8 E6 V' t j6 c ~" F5 D% m7 F
3.如何让类中的某些方法无法在类的外部被访问?
9 o- F% e r3 C1 f! \+ [( i2 { a) M% R0 ~: p
A.把类声明为private
$ k# `3 P" }- ], vB.把方法声明为private
1 @4 B3 v8 C/ p- K: Z2 s" ^3 QC.无法实现 t% Y) L' m; D( A( M% M
D.编写合适的重载方法(overloading method)0 t) P0 Y, O$ U& D
6 z9 D0 y% {; D5 k. [4 S: J
$ E0 ^1 E2 `$ ?5 t* l
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?, a0 O8 y: T7 c9 B5 o! S3 J
1 D$ m3 j8 s- O( J, ^% gA.MVC模式
$ \( H: o5 {! h( K9 J( S0 yB.抽象工厂模式(Abstract factory)
% K& A3 n& R6 ?; bC.单件模式(Singleton)1 j ]8 U* v1 ?* ^; n8 f
D.代理模式(Proxy)7 V1 R% d# [* J! B, e
E.状态模式(State)
8 X; D0 i# E8 h( A* E; B1 ^5 N X: e6 T$ `; y8 s& v
# @5 Y/ n) y g6 W
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?% Y6 s7 ~& |. h M5 B6 z" c4 Y
. I5 p u# t* K/ jA.1个
+ T, `( o: O5 ZB.2个
( z9 n [6 C" c% M W; e6 \C.取决于系统资源) R% z* b- {. I* ~
D.3个+ g R- L; r9 v& U
E.想要几个有几个1 a4 h- q: v5 A7 n, b( T! J8 I+ ^- K! H
$ K: m7 H9 ^6 k' w9 a4 ]- M8 C! k8 G4 ^( y3 Z8 Y' m' f$ h% D
6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承
# P& ]$ _* ^9 V. k9 }B.接口/ @$ E! m W6 I/ K( J
C.抽象方法
* n7 q; [% @& W' U" FD.Private方法
0 _6 H5 g V. m7 C. [0 i% {E.函数重载(function overloading)" ~1 b1 j( Z2 \* t
3 C' g- f; Y/ Z; N6 g. h; L) C9 h- \
7.假设定义了一个testclass类,它的构造函数的函数名是什么? A0 _8 u9 `% a0 g
1 L) e) n2 n4 L- l: n2 Y
A.__construct: A _8 i6 {) ]8 N
B.initialize0 U" k [$ [) t! ~$ x
C.testclass6 K4 y6 m6 a8 v
D.__testclass- M5 k( Q& N& b
E.只有PHP5才支持构造函数
6 O; A9 w5 y! {1 Q% L, y8 x2 J0 m6 l# {. Z6 f* Z$ G
2 Z% @5 O& y# ~& o0 Z8.一个类如何覆盖默认的序列化机制?7 T6 H$ l1 `, {& v' D2 X% P! M
' j- W; m- D3 n" Q4 Z6 O
A.使用__shutdown和__startup方法; x7 g2 m/ O# ~
B.调用register_shutdown_function()函数
2 i4 v4 U' V- sC.使用__sleep()和__wakeup()方法* }- O) ]) t& o2 W
D.无法覆盖默认序列化机制
$ l- d# N. Y; l% C% n; ^. i; W/ x' lE.使用ob_start()将类放入输出缓冲中, [, x1 E( s/ @
8 P6 t% G& J; ^+ p' Z/ F, K( ]" g8 M4 P
9.以下哪些面向对象的概念无法在PHP4中实现?- K" g& ]4 p$ w$ V! j
* P# ^3 g, P2 t@抽象类
# ?9 W* m3 o, X) e1 H@Final类
5 y' A# Z. q T2 Q@Public、private、protected(PPP)方法
8 g2 e) h4 b0 [% q7 y. p0 A% a@接口
: G* N2 M7 }$ Q r0 c# _0 d9 v2 @! P/ H6 @) @* ^% s) T
A.抽象类7 Y; T8 O F$ t0 x
B.PPP方法
+ [6 H/ R& t. f# J7 X9 cC.PPP方法和接口
/ D( v0 ?6 b5 _, sD.以上所有都不可用/ Y% i8 m/ H8 U. `2 q9 n
E.以上所有都可用2 k9 \; H5 W; A/ h0 P
- l: s! t, W0 `" w. n* k/ u6 k$ [
+ B4 `& c- a, @' z1 t% p r( C* U# |+ F
10.如何在类的内部调用mymethod方法?* W8 p- @9 X) J5 [* g4 y' R
+ r) T/ q8 b% I& K
A.$self=>mymethod();
8 U9 r5 Q, d4 i# d- }B.$this->mymethod();
- G- ~' `5 _( g) rC.$current->mymethod();+ W7 }# B; ]& n7 b3 k5 j8 i' I
D.$this::mymethod()
$ M6 E. Q) C7 d# c: M9 dE.以上都不对
+ C3 U8 Y! ]. U' N& g4 w) X$ G
9 }4 C8 c6 Y3 R4 f2 Q
1 U1 U0 i+ L, {- S+ m9 s2 S4 U% r11.以下脚本输出什么?-
- <?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& U1 q( T9 s) Y; a# R, m" W
B.Null: U* K! X2 D7 ]
C.Empty
2 Y7 W1 D6 Q6 ?2 s0 }) nD.什么都没有' @7 b4 |/ H6 G/ ~# j
E.一个错误* {. f: D$ ]2 j! P3 C V6 q
. q; g8 i, V3 ~" H9 L1 d3 i2 S' M e S/ |5 A( B
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$ T6 X U5 W# ~& t* s
B.5
) o% G7 q* D+ Y ^5 |C.2
3 L; Y1 K7 {1 H) s6 t" FD.Null& Z% @3 I5 l7 W+ R- d2 F7 m7 m! h
E.什么都没有5 x# g- J' A, [4 m
* Z; T: M5 \( c. E- u
$ s4 K' d( w* y13.以下脚本输出什么?-
- <?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
6 O+ v& d6 U- m. @6 G2 ?+ E& VB.10
5 G; U* ~: A, [( h7 _* e, u0 XC.什么都没有
' e N# _9 G' E* qD.构造函数将报错( R/ V& M, J9 m1 y
E.510* i! B0 i* G% Q' T! M
0 w& O% _" O" d( b) f
7 N' e0 q& W$ k; \0 E14.考虑如下一段代码,执行时,$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函数必须返回一个值$ _2 Y( X* S+ N% Y' \
B.reduce_fraction函数必须接受一个整型值' l; {& w [( A7 \- v# W
C.gcd函数有问题
' i6 W2 E0 j% cD.必须通过引用的方式传递$eight_tenths对象
* D+ l; w+ E( k& Q$ LE.对象的实例不能传递给方法以外的其他结构。
$ V s8 O @% M2 ]; u6 @( x: n$ j& t6 Q
6 D% k8 F7 J/ L' [' l0 a
15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法1 s( \' B$ u/ U1 A
B.生成myclass的实例并调用mymethod方法, A5 q8 j6 u! I! p7 f0 w
C.产生一个语法错误
, f! d" b5 x7 P( i5 Z& U$ b# w* fD.默认myclass类最后被创建出的实例并调用mymethod()# W( _) Q' J% u( p8 h1 w: A
E.调用名为myclass::mymethod()的函数
) S; y* Q9 ?( A
5 S1 a( G4 R5 ]" L9 r- A: v$ k+ d! I
16.PHP中有静态类变量吗?- ]- C: I) c9 y& t; Y. [
; s' e6 g# M+ q) IA.有* u+ a7 S3 ?1 R# e
B.没有
3 z9 \ K3 \3 m( l2 q- m8 M; X v( a0 s! c8 o- G; k
& P0 `+ D; ^3 Z2 H17.以下脚本输出什么?-
- <?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
5 d! M( @0 g/ l/ d S) N% N9 r. `B.2* j8 y! n- k; ?
C.一个错误,因为没有定义a::$myvar, Y8 ` ~5 \. F; m( T# y
D.一个警告,因为没有定义a::$myvar8 V: w" L* V; D: ^1 i% A9 f" s
E.什么都没有
[+ T' w5 @: U7 L0 j3 P2 F Y% |* e# N( S5 z7 c+ m5 M" _" P) M1 c
/ ]4 t6 C j2 J) W% {
18.如何即时加载一个类?
% E7 R. P9 F$ ?! J
( ~& a$ E0 K$ A$ j% j% d `A.使用__autoload魔术函数
! N; {4 i% y5 l. N# L' I5 m6 cB.把它们定义为forward类/ e- Z" i0 T9 Y& X. ]
C.实现一个特殊的错误处理手段/ r* `7 a6 I; b' w4 `/ L
D.不可能
% A$ r$ }# G' [; iE.用有条件限制的include来包含它们
0 J' C2 p8 K4 f' b' [
8 r# s6 a% `: I# e, g% h9 h/ Y& k* @& |/ Z' H: z1 ^7 f
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?0 d' [2 |6 h' R& d$ H/ v
( i9 x7 h) r" z* z. E 答案:__________
, _ ]/ ^# ~0 U
5 _' a$ s, u- _, a" S* C2 X5 P% x$ n, S% i% Y/ ~2 h) G
20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called& z1 L# D3 L/ i7 r! h: J
B.一个错误
% W$ }% t1 G+ L k- |4 oC.一个警告9 \' Z5 U D( L2 H4 g" g* s' U
D.什么都没有 _# W; w/ P Q
, O& w) D1 C7 w. @" W
& w8 `0 | }2 V9 @: n! k N/ W8 f* j
# h" w2 @9 ?8 Z& y0 p
答案速查
! r, f9 M0 r: w1.类
" G* T& }. D+ U) u/ c8 o2.BCD
0 l* g% G" a' N$ `3.C3 J# `0 g6 c& Y ^5 K, a; B
4.C
' o/ ]; C6 l/ p0 J5.A
: u3 Z. X( q& j; x6.C! a+ b. f/ D- G1 J0 ~, P9 Y1 u
7.C
8 Q& B( F0 G4 s! |8.C
# h$ q. I- Y& W" u" p9.D
0 S! d2 u) _! a) c2 H4 h9 w10.B V3 I ^4 m3 k. F1 m$ Q
11.D) y; x5 ^8 l+ |& H
12.B6 j! p p" W5 X7 l1 x" s# l1 p
13.A4 {7 `: z/ P* f
14.D
. W! G8 S; `: W+ s$ z; g% s15.A
1 a, F# ~' V2 G) ]' n6 h7 _$ {* z16.B1 u" B- B+ X0 @8 x+ T
17.A
& a; f. M6 R+ d! _18.D% E/ Y# x8 a2 T) I! s
19.设计模式; r2 l3 G& y: Z
20.D
' h0 V7 i) h! P7 J& a# _5 z
0 E* V' s+ a4 P1 n- A' _4 q* C: P2 F/ p! n
' R/ i! @8 ~. H# P6 d答案详解 X+ f1 R/ m/ v e2 y
" R( A; ]3 E) n" Z' [- C3 b1 g
1.类是对象的蓝图(对象是类的实例)。
# I5 K! l" t& B m9 Z) u" R2 T3 f3 E, j. `5 q' H8 e
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。! F3 e; l% k( ]! u" l
. C6 F: d! _2 X# I' b" F# V- u4 x3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。
$ ~) g( l" r0 H2 j2 X- k- L
( l) T% L, y8 s+ p+ w: I7 i4.单件模式可以限制一个类被实例化的次数。) A% T0 E4 y% z9 A
: S) o; T( i% y7 z1 r% h% x
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。" d/ o6 Z t# v, d% I5 V
9 h7 e* t& |6 g. `7 m7 S5 T/ M6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
) V3 o/ K( s5 t+ b0 y# ?. M1 J
) D. P; s6 n- p7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。% i R& `4 Z8 N( W+ y- M: g
' n) W" ^6 E: [: i3 _) D
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
8 I* p! ^" L; M E0 S: p9 H
+ P$ J# U5 \! h6 T0 z1 c1 D& k6 p9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
( o7 [# T- E2 B" b. s0 z) k5 R
- e- C+ {, o5 v10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
( q9 f+ K- h" x6 L$ {4 W( H" O
5 D2 v+ h9 I5 o9 C0 w# K* r11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
' J* o5 y- ^7 N, v2 ~
, b2 N8 T: J5 R5 h4 I9 F12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。' O2 P) U" x3 o$ v: v: ]2 A- t
$ a6 S+ T% i0 [) }0 X" V/ s
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。
0 Q: ]5 n, {& W( n ^* D' H' S |' ?
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。' |6 z1 M7 f1 m" f7 e. t& p6 F
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:, h' D, _2 Z; D
function reduce_fraction(&$fraction)
7 s' @; U0 J- h, |0 R- I答案是D。
5 H8 E3 T% y: H& y
/ j9 t0 R" D3 S1 `0 J! R4 e15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。$ v$ x ]$ L; O5 M( Q
, v1 R4 m8 P/ i$ `8 j; r" @
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。0 v9 D) f9 M3 T* F' k/ z( F
2 v* E0 r {, c$ \9 u/ Z, w
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
f9 o2 u' A4 Y! M( E# j$ t" s2 J: t+ f6 {+ s5 B Q p
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
" W5 K2 f4 Z: t1 |
0 Q; V2 J% |- p ~" ]! [19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
. T! X2 [) t9 p) N6 o$ Q
# P) {- b# z" M20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|