  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14159
- 金币
- 2370
- 威望
- 1647
- 贡献
- 1318
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。* B! \ x* O4 E* Y, G: V
PHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。
+ h# w+ Q- z& [& ~$ F9 D本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。4 a: v0 B# n! }
% K P% u+ ^% }/ s
问题
9 S6 G! F$ p# ^" Y) P2 [3 O# v9 ?+ c% R% k6 ~* O3 t
1.对象的蓝图是什么?
9 m. q" W/ m5 n: Y/ J! ~9 r
# {% a7 e5 a" ^- p答案:____________
5 D' W; c" ?) R. {. k
* L& h) S; k5 c' N( c& E) _
1 M& R3 q2 P) J+ ]2 n2.以下代码执行后,数组$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
$ l( M5 H4 O/ x% d9 N5 wB.b
) T. @3 C( }) q2 v |0 oC.a+ ~* {9 N6 Q# K
D.d
% M8 Z" p# {: Y$ p9 o' v4 eE.e
) V+ N: G# V( l! {3 y" n- C1 [" s9 m/ G
0 m1 ]5 x2 z! I; K
$ q0 X/ m1 s# t" [8 V3.如何让类中的某些方法无法在类的外部被访问?) G0 O2 h( q: S4 ^
Y: O z1 Y' rA.把类声明为private
" }, O) i; `' k: mB.把方法声明为private
Y/ e0 j; C8 L: H h- {7 bC.无法实现; O9 l/ {$ L8 V, ^3 }
D.编写合适的重载方法(overloading method)
* O: H4 l. l6 ~4 @0 Y; K L! a) A8 G' A \: C1 j4 ~
! Y6 A+ I) t) Z: n8 C
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?
; K8 {$ |, M/ {$ ^% N. ], h6 h0 z
A.MVC模式
6 b+ J+ R0 _" z" X/ y& {B.抽象工厂模式(Abstract factory)
7 O7 w. Q% X7 V6 B& qC.单件模式(Singleton)" c( X; G' f0 P5 x) B6 y! M
D.代理模式(Proxy)
- g9 x4 B; X' O; H$ [' kE.状态模式(State)
( B& \7 D$ F& g) A1 ~5 F; q4 r* s; Z6 b8 {- X8 ~( w7 v
- X; B) P3 l7 Y2 i( k" u
5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?( j, @# S' K! c# k( d5 [* `
. @) L1 s/ T* p) u( M
A.1个8 c1 _' E2 i V! W% l: r) @
B.2个. T0 m: c' O- f6 X( {
C.取决于系统资源
9 N2 h7 b& r! jD.3个
6 f' E# m" V6 y6 e8 P2 VE.想要几个有几个
) u, {0 k- y4 g% e
0 y5 c' \2 M! M7 v* [ z% m5 `8 d" {# F$ _
6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承! q$ k* a8 B5 g& |
B.接口) W: E7 w: T8 v/ @4 ]' O4 a7 i
C.抽象方法2 Y `9 T# {5 z# z
D.Private方法
8 K. `3 H3 ?0 q8 }1 bE.函数重载(function overloading)
6 m# l: w- f) o
8 ]" q' {8 m! I! A
1 I+ ~" [9 d1 V. g7.假设定义了一个testclass类,它的构造函数的函数名是什么?
* H( g2 t g0 p! k+ t" d' t: N# q" B- w8 p1 Z5 L
A.__construct" K% Y3 F7 k5 P2 J
B.initialize% I: u9 H' C/ Y9 b( N! m, Q* X
C.testclass
) c% N4 M* J6 C- t3 {+ p3 B% HD.__testclass
* [1 e8 Q5 K- t+ U" Q1 lE.只有PHP5才支持构造函数
) ~+ J1 y T3 V$ n r
3 k* S0 V& ]' k) }, Q1 \; {$ }' Z$ _* r- X1 ?& O: ^; L7 f* v2 b/ J5 d
8.一个类如何覆盖默认的序列化机制?# X e0 W4 C# O4 v, ]+ [1 ]! h
/ j/ C+ J, e5 \% b" ~' RA.使用__shutdown和__startup方法
. l0 y) O. o6 q; a8 |. oB.调用register_shutdown_function()函数+ l* @( g2 h0 F) r- T8 h$ M, I7 A
C.使用__sleep()和__wakeup()方法
U" t" H3 |9 l3 jD.无法覆盖默认序列化机制
) Q5 E; M+ L5 y# @. c( _E.使用ob_start()将类放入输出缓冲中
4 f7 E+ d8 p' d5 I/ z" }; O" U0 z4 H9 x& }/ c5 J- M' J
" O, V; ]3 {6 i7 g$ Y
9.以下哪些面向对象的概念无法在PHP4中实现?; ]$ a0 Q- N" I$ I" H; @. M0 t
% H n$ h2 I+ i. u. k4 I9 P7 k@抽象类
9 e0 ?; C) F- u@Final类* M: l; _) ^" U, ?8 o3 Z
@Public、private、protected(PPP)方法
. X. X; U/ U6 t2 Q@接口
& F) p! r2 ^4 q2 {
2 J. f. D$ `6 k: e! k0 g( jA.抽象类+ p! t* y: W+ ^+ L- b5 h1 \
B.PPP方法/ N: q$ y+ ^$ q' }2 z
C.PPP方法和接口% M1 L. B. F' Z( B3 P- F
D.以上所有都不可用% ^ {9 h8 `$ B- a3 V
E.以上所有都可用
; B- [7 f& P% c: I ~3 h3 F7 t" B: Q9 m+ j- J. ~6 s( o: p
3 j- c) h* m3 Z# c10.如何在类的内部调用mymethod方法?
$ m( e- f$ D# X) |/ p# t9 v6 f7 Q' v( w! ~6 a e
A.$self=>mymethod();2 B& ?! X6 B+ v6 \/ j" t# F& i
B.$this->mymethod();
: e3 t3 g/ p Y! i2 K* jC.$current->mymethod();0 M h: f0 u% X" m
D.$this::mymethod()* _) J9 ?6 s- S6 }: P8 T0 R
E.以上都不对
" V; u( L3 @# K: d+ ~
- S2 U& G: c% O3 {
. C: B( a' z% s4 J& }0 P11.以下脚本输出什么?-
- <?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' m2 W1 \& Z7 k# L1 w6 T
B.Null
) `/ D/ P+ c# i4 l- l$ o2 [, wC.Empty
2 F. ?: t# {2 X2 U2 A7 d: p0 E* h! ED.什么都没有: h4 v+ }" t8 j) a0 e1 \% |
E.一个错误6 s8 `+ K- f2 o2 z
* F( m# z; F0 l. q# I( S
/ u% y4 S& |8 F1 g% F12.以下脚本输出什么?-
- <?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.105 R m( b8 T- X0 H
B.5
9 J) }7 Q: z& q+ j5 r) vC.2" C7 ~) l3 I7 z6 M8 v
D.Null6 {1 I/ n. F' @6 ^) I/ f/ H
E.什么都没有% a! ~& d$ z8 M+ U) `" S
* A) M2 n8 o' @! v7 b) ]2 h# w
1 ], Y2 e& U1 \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.59 I" P; ?& Z' Q8 P4 s5 G
B.10
4 i/ I7 p+ k' ^/ F# WC.什么都没有6 ?% l, H- K. c$ b, s8 ^
D.构造函数将报错
7 O8 b9 r, Q" |E.510
A0 V x5 B5 I& t* W1 Z: |( d5 [+ C: [
) g& O8 k4 w" f14.考虑如下一段代码,执行时,$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函数必须返回一个值
/ g% J* g5 r. \& jB.reduce_fraction函数必须接受一个整型值
1 M. V/ _# F: v" g& vC.gcd函数有问题
; N! p' n3 A# N, ~6 w/ mD.必须通过引用的方式传递$eight_tenths对象 r5 ~- m+ X$ t/ X; a
E.对象的实例不能传递给方法以外的其他结构。; a9 v0 V% j6 j% Y+ \. d6 N ]
* x4 P- A9 |4 O3 }( g8 `3 j" J
7 F; R" {$ ~3 z15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法
3 Z$ V+ o, F/ e( } b, KB.生成myclass的实例并调用mymethod方法
5 u8 S, e: a1 ~C.产生一个语法错误
, v: e9 ]$ y; k) v3 }D.默认myclass类最后被创建出的实例并调用mymethod()3 |$ B) y/ H/ c. r# ]6 I
E.调用名为myclass::mymethod()的函数
7 O4 }5 R' O& n3 I, B4 Y4 D4 L6 ]) Z- Y
, x/ Y& l3 g4 h# o! I5 {
16.PHP中有静态类变量吗?7 \' g$ J' ~7 W0 u
: b) ]' h7 P9 \% [% h
A.有# @. [! B8 p* Y# L$ n' d
B.没有
/ {: s7 ^, e* _3 R- W8 [) Z0 W3 Y
7 ^, c1 V& i% [. t( `: q& w$ q. e; V
2 D6 Z& @- t! C' S1 k( e17.以下脚本输出什么?-
- <?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
b; w$ w4 y6 \; _' M" U! z# dB.2
- S! G: h* I2 d3 rC.一个错误,因为没有定义a::$myvar
3 `1 P8 M/ p/ \0 yD.一个警告,因为没有定义a::$myvar' p" K0 l% }; Q5 r& g' _/ q0 ^% X# A7 b
E.什么都没有% i' `) h- w9 a8 P+ i
! s- S$ e$ y7 w6 o( D8 u- K
7 J2 y u/ d$ c8 b! w; V3 W18.如何即时加载一个类?
N, ?/ m2 M% {7 B3 {# O. ^8 ?* s8 e3 D6 O( a4 @
A.使用__autoload魔术函数 F; S# \& h7 N# r" i, z5 a, X2 a
B.把它们定义为forward类/ Y+ J7 r' U( J' T# C$ T! h
C.实现一个特殊的错误处理手段7 ~2 l/ K, B* Q) Q: H
D.不可能+ K5 c( v6 z0 E* t
E.用有条件限制的include来包含它们
, X9 o& [1 z+ i, V1 n2 v. e9 r: x- y3 h0 L6 t
2 I" Y, [: u) Q" a: u2 G19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?. j* M- k: @* _
4 }4 h& n1 J! z4 T' K4 P 答案:__________
. ^2 r. [5 O# f* n7 H4 ~* \. U9 z' j0 g; W2 x" q% ~, e
! [: |5 I' o. D& W. U( [, E3 O+ G20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called! u! q* h( j0 h+ l
B.一个错误
t4 W6 W& \! `3 f# |C.一个警告
0 E; C1 [& @: m' i4 k% MD.什么都没有# O8 T; f) ^( }6 R' S
- d( m# i# C0 k
* G8 A, ]; E1 u# T
+ q4 `% C) U/ u: D, t9 O答案速查; J) m$ L9 h# Q. S! ]
1.类1 w+ v3 y6 @$ Q
2.BCD
4 E4 P3 Z- f5 G: L3.C9 |0 e+ ^$ |* p
4.C6 _5 z2 k$ a" _7 r6 b( v! ^/ n6 P/ @
5.A: a" ^' e0 D& @! |# G; ^
6.C" i' _8 z0 b# G' j
7.C e6 k( A3 I/ a# e
8.C& {; |( y" j. Z
9.D7 ?1 k* \; \9 o
10.B
; P2 z7 m* I& n11.D
; i' O+ Q0 G: x+ u4 Z" V12.B7 T2 {6 |" ?2 e! n; c0 g
13.A
# H! M7 S- G8 v/ G5 {14.D6 k% T0 A# g1 E# A" A/ f1 u
15.A
) i% p! H( ^ y16.B
5 I" I* Z9 L% z17.A
. L% q. I( k" F1 c. Z18.D
G4 h# o' _2 T/ R r' e19.设计模式* s( I; X$ ]0 X1 ~
20.D7 @8 T( n1 [$ Y+ g) k2 \
. H `% Q+ ~; {) V4 R9 v
" Q. F8 H3 B s: A6 a8 a. u! N1 i1 r) x5 _
答案详解
* K5 d6 t, D/ C1 r9 e# m4 i& T8 n1 a1 _$ l: f4 s& N
1.类是对象的蓝图(对象是类的实例)。
V" C6 i) r1 A9 C. ?3 b D0 R, | z2 ], i
2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。9 G% E* q. p! g, B
) D [% v7 {9 V
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。* E4 C3 ^: Q$ w
& L* c% Y( ^0 C7 J; D4.单件模式可以限制一个类被实例化的次数。
7 l4 M2 X: S" j8 U2 i I% X$ j2 V. c% l' b6 f
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。: T" u/ L5 v% b! B* o( A1 B) q
( H9 F* z$ I+ l1 R& ^5 r4 H
6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
3 ?4 j- g( c5 l7 K
: {* H7 n& H5 Q9 g; v3 _2 x7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。( ?1 j2 [* T+ ~( _4 A* H7 e3 Y
. c- S% B; M) s% M* G4 f8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
) w+ `0 w$ L: H, ^# Q8 Y
5 g$ s2 l! b, z' N4 ?9 M5 D9.PHP4中没有题目选项里所列的任何一个概念。答案是D。
) n; S: _. l1 f- T, Y5 q4 R1 H" Z. d2 v( t3 ?2 R# L1 _% `% D5 i4 m
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。3 v7 U7 W( i f4 c" z; R
, _6 U. D2 l1 p0 C2 I0 g( @% t6 r
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
# N: p3 ^. p4 ?1 ]$ q( a
& f8 v+ H6 h, h% N# R4 x* J, @2 k12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。 y+ u |, e% B3 l; k! K
+ |; O$ T1 Q d# y
13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。! S! T* _2 Z) `8 f- _5 E
. E! }2 @) O2 K2 U
14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。6 M9 U3 a- R, I. @
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:4 X5 C6 |5 ?2 y; x
function reduce_fraction(&$fraction)
, ^5 V5 B& P* D- D7 {答案是D。5 `) [- z2 [, {
, d* Z; Y5 y5 j' R' N15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
& S( X1 H+ C0 z: p1 i1 F; [3 R$ U
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。& t6 p; S H0 l, s& m' z$ {
( o) }& F+ O! }: S" T' B17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。7 o2 y4 }- g# ?4 [9 c
( r/ O- v, Q+ N+ g' b% G18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。3 b8 T7 ]' B! b
0 {* l9 H# l( W
19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。7 c9 \) [+ O3 g" ] \9 o
6 X: Y* U; _1 e
20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|