  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14247
- 金币
- 2414
- 威望
- 1647
- 贡献
- 1362
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。( Q( g+ R* w K9 v, y; |3 H, M
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
1 k- C5 L3 t% [2 s2 c. ?本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。9 }7 s" N) o" n2 x
1 M8 a4 y+ \5 y% W
问题
* h$ l5 r9 I0 e, Q0 r5 E! a7 ]6 R% a' Y8 w4 W8 n+ Q
1.对象的蓝图是什么?
' r: W& c8 f* u/ I( y/ b* F0 @# J3 C( s) g+ R1 E R
答案:____________
; j7 V; D( d3 w2 D- V7 @: E+ [2 d: e- g. V* a' L9 y: ?
- D y+ j' y& m/ ~$ w5 m
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
6 l( ]1 N( ~! V1 LB.b
* R( g' T, s e1 `$ j) T bC.a
) M1 G( I- I) t3 ?2 H# a# iD.d9 O/ h! X5 J- d& m
E.e
1 [3 R" K( [9 ^9 L/ z0 Q; ^5 m6 `6 D, D+ E/ d) `4 _
4 I9 L7 m$ [+ t$ l
3.如何让类中的某些方法无法在类的外部被访问?5 X4 @) u9 ^7 f$ X) X2 E
* V* |7 l/ i/ O2 j2 [, jA.把类声明为private, Q/ w3 h; @3 t0 n: ]
B.把方法声明为private
0 W, o5 \ l3 k2 XC.无法实现
( `1 q; o/ i1 h lD.编写合适的重载方法(overloading method)
2 u( r. x/ A4 {8 K+ R$ B
. | w0 d" j. X# [. ]
" J8 J. Z, V i& w1 Q6 E4.哪种OOP设计模式能让类在整个脚本里只实例化一次?+ v. |& ?! j* ~1 L( }. H
8 A( ~7 T0 d9 y
A.MVC模式
4 I# l9 n8 f( a; g0 t& eB.抽象工厂模式(Abstract factory)* @( y% Q" t4 O
C.单件模式(Singleton)0 h$ L6 ~) m; \1 p0 ^- d
D.代理模式(Proxy)
! y1 R* X" j9 dE.状态模式(State)8 q: l) p+ C' J& S
- a1 p/ G! V! N1 V
+ b$ d! I& ?' y3 C5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?+ T$ o' u3 l0 `6 t: R$ @# | |" m5 ^
; j4 {" i6 _0 \ C8 J: jA.1个
" U' Z) L' q% J4 V. NB.2个+ r$ j( f; ~: ]$ W
C.取决于系统资源4 R# F, U& B* |2 _7 ?& R
D.3个& J, D. R6 ]3 B% Q' V
E.想要几个有几个
* k3 I4 Z/ M2 e M* J
/ H' q0 f0 e* x5 L# L; M
+ j, V0 m3 Q l D6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承. Z/ Q' Z4 C4 I7 b
B.接口
; x4 n8 t0 q) ?1 }2 E. YC.抽象方法
" N/ N6 J9 o0 p) A$ j. ?7 fD.Private方法
3 P" z8 t+ ^3 y4 \E.函数重载(function overloading)# `% K1 D! [' O: Q% {' u* ]2 ]
2 K( k+ X8 n# ^% ^0 o' c
, r1 ` s' R. X0 N4 J7.假设定义了一个testclass类,它的构造函数的函数名是什么?
7 R1 ], z: V( D7 R
1 {( y6 l5 B9 \! l9 f% q- vA.__construct
" x6 e6 Z3 t3 MB.initialize
$ O2 Q2 |2 ?( Y( @5 H7 \! H+ I* KC.testclass7 J# h- T0 |: ]/ s& n# ~
D.__testclass
! T! g: i$ Z8 b) N' a' zE.只有PHP5才支持构造函数: ~( ` n* Y8 @, X2 G
( g: I6 _" s! I1 D" E$ ` {- B/ S7 E8 u6 s0 J7 @! t
8.一个类如何覆盖默认的序列化机制?
$ b Y( b5 K( u+ u& g- ^' x- X
2 I$ `5 Y3 `( ]2 X8 n! X+ u0 MA.使用__shutdown和__startup方法
4 W! n" [$ B0 i# ^+ o0 X3 ~4 |7 D' mB.调用register_shutdown_function()函数
( L: c5 G8 d7 GC.使用__sleep()和__wakeup()方法8 |, z9 D3 x9 O+ p4 @
D.无法覆盖默认序列化机制
; N7 x, A. W! P9 k' M, n3 s3 xE.使用ob_start()将类放入输出缓冲中
/ C( m2 W1 ~7 d- n/ w
5 W+ V3 x" V: H# D! `' H) d ], l
* o; Q+ P+ G s3 ?9.以下哪些面向对象的概念无法在PHP4中实现?
3 Y: B6 N4 ], W" C* d0 O* ~: P- B& }9 A( K+ i2 g
@抽象类
: V# V5 D2 B2 h, V8 e8 J@Final类* I) a% z8 Z3 s/ c3 o
@Public、private、protected(PPP)方法4 Z* I" q' e8 Y& {* s4 {4 @
@接口! w! o" e! M6 c$ x" c* W6 R) d2 F# U! a
3 N) K" F# L- X( U' ?* g
A.抽象类
6 o! T! z% E& c. T: XB.PPP方法
" b! Q9 ]! z, h# R$ a. sC.PPP方法和接口; ?0 @3 Z% I0 V" y* h
D.以上所有都不可用$ d! N4 }$ k3 A$ X2 v$ L: z
E.以上所有都可用6 S( j* X. G F# F' r4 o
& C" |3 T! d# n4 m" [' `3 W( K' u G( i$ | H1 J
10.如何在类的内部调用mymethod方法?& p: P- d8 E3 G; q K- U7 D
. j+ H% M% y6 _( Y& Y! j2 c# BA.$self=>mymethod();) Q5 A6 @& e: X) ]9 ~
B.$this->mymethod();1 d9 [4 T, h$ \! m+ h( N
C.$current->mymethod();, D! @ L% ~2 x+ X1 w" Y
D.$this::mymethod()% E* {) g# @. e+ x. Y9 k
E.以上都不对
: v) p) T' y# z# ~% B: z6 Q4 U3 [* W7 H0 A# b- ^, q: y$ {
1 S% R# y, B* |6 y. k X11.以下脚本输出什么?-
- <?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
' W4 w/ v3 b: Z5 ^% H9 eB.Null
, H1 y7 [) t. N; C! XC.Empty
E, n' B! ~/ Q8 GD.什么都没有" o0 x( s7 }2 J
E.一个错误
2 ? W$ u. Z& e8 n6 Y" K- ]
/ }, f% s& v* @' l
/ d* B1 D( c! [5 p12.以下脚本输出什么?-
- <?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
' m' g+ H' D& Y! M/ bB.5$ a$ y* Q8 m- f' f' \
C.2
4 H& y+ C5 l3 i3 oD.Null
C# B( G2 U6 ~0 V4 q/ e* q1 JE.什么都没有
: U- c$ T p( T5 w! v- m: s, D# S- P8 Q
M; i# L- x: B) z13.以下脚本输出什么?-
- <?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
: T' D8 u1 R# W7 |3 oB.10
& A6 C6 Y% M' i( o; _C.什么都没有
/ i, s+ t$ Q U( z0 z% vD.构造函数将报错
, d8 A2 D: A! a6 f+ q5 d! N' [# h/ h: GE.510- z& U' l/ p" }$ X% v
$ s8 R" B- o! y8 {( F5 S
3 j* P# v" F* F2 [: x J$ f
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函数必须返回一个值
( j3 t; Q" ^# s: XB.reduce_fraction函数必须接受一个整型值/ T: R, A# ?; x% f, ?
C.gcd函数有问题- [8 q& G0 P7 R) n, Q: t
D.必须通过引用的方式传递$eight_tenths对象8 ~, H: j- F/ S$ a, @
E.对象的实例不能传递给方法以外的其他结构。
% S0 d" p+ i7 p6 p8 D( O- @. Z: b' B# Z; g; f
+ T% I4 w0 W) L3 c8 c5 u15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法
/ S2 v. ?) p; H# l4 J9 ^1 [B.生成myclass的实例并调用mymethod方法
4 b% q: y: s6 h* LC.产生一个语法错误
. d( d$ M' U+ a6 N" C! LD.默认myclass类最后被创建出的实例并调用mymethod()$ B3 o" O% f' Y# j* B+ }3 t& O: c( M
E.调用名为myclass::mymethod()的函数1 F2 i1 O2 L- C4 O: V3 Z
% u$ w" r& H( X; R/ c% o( B
1 ^) X4 q0 d/ e2 `7 p
16.PHP中有静态类变量吗?5 Y' y: Z0 C# h1 J( N
$ d; u( H! T2 `) n4 Q/ d; X, w; pA.有8 u* s) d$ g- ?1 D4 r* H0 ]7 o
B.没有4 Y/ r! H. G& V
0 Z) _ j) @ }: w
$ r1 R0 i% _. i/ x- l! n- 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, Y; I, F ~( Z" I! s" L' B
B.2
# O" V0 g% c3 X# XC.一个错误,因为没有定义a::$myvar6 _% s# I+ l& Q* \9 D9 b- \
D.一个警告,因为没有定义a::$myvar9 K. u3 Z9 D1 R7 ]4 B
E.什么都没有' M$ P4 D( p; z# i7 l) G7 ^
$ r6 U0 p: M2 g' G$ q5 ?
; R' \) C( x# z( p2 T' l+ M18.如何即时加载一个类?
! f; d& ~1 \1 Y) a+ @9 X' _ Y2 |( Y! k% M0 e8 K( h
A.使用__autoload魔术函数
* z A" M/ P* y6 nB.把它们定义为forward类
8 `7 l9 u4 f5 d" u) Y5 e# u1 OC.实现一个特殊的错误处理手段; V& X; ~7 \/ `5 u" l4 b; O
D.不可能' f$ N' ]! |% m
E.用有条件限制的include来包含它们7 ]* K) _5 z6 ~8 h+ b
; p' e. l2 \* p- a& n- E5 m8 j U, O
/ y: b% b3 a* X, ~* K2 O
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
' D$ C" t. D6 H! T1 k0 J( b- g
+ O7 I* w; d; p6 t 答案:__________
$ F+ @) x+ L5 Z+ l( C4 j, P
' w5 H+ a0 A. C$ _% l L }; [: m5 C# E6 W/ h
20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called0 N1 |) y; N& l! l
B.一个错误) g! K6 X+ R; r
C.一个警告5 A: X" W. c' R& r
D.什么都没有: L6 K8 L2 D- g5 j4 n
4 H0 K' g4 i$ D/ [
' P% k8 M0 @# S& e% c3 U
% d. w* G6 c2 K4 h0 Y答案速查; C: s! e) J, t0 v
1.类
2 ]! _/ Y# _, F( P( ^5 y- r- S m2.BCD
5 e# G0 P# L( B) E" f( V( r' G3.C
: ^2 R0 ?& J! ?$ U9 U' ^4.C+ x2 M1 O' z7 }% P) T
5.A2 b) n* }& E- x0 W
6.C% D6 r2 v& |) e* L' @$ s; C* ]
7.C
3 ]9 \7 s4 I. W; X9 h8.C, ~' p) e$ ^/ X; R; j5 i# Q! V
9.D! X3 v# p |1 a* p( ]9 `. r
10.B
$ Z( u$ D2 C1 f2 ]- U' G11.D; Q" p. z* G7 r& u y5 |" E
12.B* X- C; S" o8 p4 O0 ~: W
13.A$ t0 Y! b9 m* {7 {7 X6 R* o; r) }# J
14.D3 w; b X3 v9 z* F# j) q
15.A
/ E8 M+ O* k; g' e+ V) N16.B
0 v) p) Q; V/ l8 w; A; t/ }6 d17.A
/ E4 U1 C6 r$ F5 k18.D8 e8 @- m# y5 [4 l
19.设计模式
6 ?8 L9 g' @) ?5 ]6 @. A) J" E% o20.D
; G H0 S' z9 }8 R2 u
3 V: m9 R, C6 \ O! F
# O m- S& \5 C- P- [; ^: R* @% b& Z3 d
答案详解
9 p7 `9 t7 a; [+ h! s/ D& i
! f- x( T7 A/ F* Y* i& F/ @1.类是对象的蓝图(对象是类的实例)。
! B' c& f. u) m p5 @; a% R+ b* s2 G8 N7 |" b
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。9 r0 Y0 D- a$ V' f
( s$ J! {5 C- y' }+ _' x3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。" M; t% W K4 _ p; z; Z. `) Q
6 a1 e0 M8 z4 F/ q# B
4.单件模式可以限制一个类被实例化的次数。9 k# p+ d! w9 {7 ?- k
: a; y @+ U$ H5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。
6 K" q# u' ^( ^3 T' Q' Q4 n' O# g4 V7 c+ u% `% o" A J
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
2 [0 ^% [- z B! F. ]
" ]) W+ |! _0 B9 w0 c1 I7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。
1 ^# T& @ r4 H0 Y( a, n6 }- e) H/ V4 r* a) k+ u# v" N9 Y( T
8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。5 h' X C! ?. h5 f, L
7 f3 G& o8 f8 L7 }+ [( b, k
9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
/ x+ a4 \" `: |* U5 H5 J) B4 N/ n! r* K" o. @# a: u7 [, A% a5 L
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。5 o1 l7 V! V) m8 k9 j7 f' k
7 m z% p8 Z# x- Y" \0 \3 h
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
3 E1 x* a5 M) |% o* {) {/ _0 z" I# Q! u0 k8 X
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。& u: j2 q' T! ~ y" r
+ J: X' ~9 u0 S, Z0 M13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。$ h) V1 F1 _. A) q- K* z) Q
( B: k& E; d% A. F+ h
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。( Z" k, K% c# l* I# N: ~0 x8 H1 I
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
4 \6 y! W" Y, x/ y" ?; ] function reduce_fraction(&$fraction)
9 K# n$ R3 o5 j2 x; v; C% }7 b答案是D。
! y/ w2 `* u5 r. R5 j2 ?% O4 d4 Q7 b0 }: h. I+ y
15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
/ q; a+ ~2 G0 G0 v- f, E& K
6 U+ O1 e4 B4 s) ?16.没有。PHP4只允许声明静态函数变量,没有静态类变量。
: s- i' y+ l* T. s* s$ ]
$ g- `" O' l6 E% B t8 x9 p+ ?17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。
9 v6 T( I* J/ C) C% v+ |8 Y8 ?
- C4 b1 X: ]0 f8 B& D18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。* \: a6 N5 u% u N: r# A8 R
& U( o' O- Z( U2 h& q9 m19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。
w) o" _7 c6 M: s
% x0 z* ^, m* X4 S20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|