  
- UID
- 1
- 帖子
- 738
- 精华
- 28
- 积分
- 14221
- 金币
- 2401
- 威望
- 1647
- 贡献
- 1349
|
[Zend权威认证试题讲解]第二章-用PHP4进行面向对象编程
尽管PHP4的OOP性能不强,但它还是能够被用来构建可行的面向对象的代码结构——只要你知道对象模型的缺陷,并且小心的处理它们。
& `. M- d z4 o/ q% |8 k6 W/ U8 I/ j9 z5 lPHP5在对象的处理方面做了很多改变,你或许会因此更倾向于完全忽略PHP4。但事实上,许多用OOP的程序员从很早以前就开始用老版本的PHP编写软件了。所以,大量的OOP代码早已存在,甚至在人们跳到PHP5上进行开发之前。7 I4 E/ n; O7 j* F9 W/ s! _
本章不仅考察你对面向对象知识的总体掌握,还包括对PHP4特有的OOP实现机制的认识。9 N+ J, `" w+ k
9 f/ s) V0 j: G! R
问题 E1 X( @2 R. O( U5 Q& u
+ K8 p; u1 X! F, N P
1.对象的蓝图是什么?
: R# u5 g A5 h7 w# M% k! A5 K [; @5 j+ R U) ^3 I
答案:____________
% ] j0 j Z' P7 G* z, `2 y% ]9 B* W9 m# U1 A7 ? T
1 v( A7 V* b0 W6 D/ F! Z8 O' E2.以下代码执行后,数组$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
; T* u5 X7 j% j6 e/ |9 cB.b
- g5 z0 |0 k+ g' }5 _+ oC.a$ \3 Y# L& k0 Y$ N# U& x6 J' \
D.d$ d& e+ x0 c9 Z: a) \7 d
E.e
F, x2 P; t- I$ i, t/ r4 B& h1 ]# z
6 k3 J: f: D( H2 i! K) c$ t: c- k# E$ i* i* {2 W) j
3.如何让类中的某些方法无法在类的外部被访问?' S X' C; P$ I8 K; [
2 w+ R% B7 i \. j% n' X0 J$ jA.把类声明为private/ r9 V" {$ X. d: A/ V% {# K
B.把方法声明为private
( }% I' ]% I, z+ b- p/ T" yC.无法实现
9 k ]0 Y* W: b+ W @0 SD.编写合适的重载方法(overloading method)
- F$ _7 m! w# A# o8 B( s. _* n) y1 x0 H6 R4 i$ D9 _$ o/ z& [2 i
" m2 S V) e2 D: j4 E2 k* u4 t
4.哪种OOP设计模式能让类在整个脚本里只实例化一次?! l6 i2 U0 G5 \+ i4 e3 t2 J
/ c6 |; O+ e0 J! N1 UA.MVC模式
% A5 z2 R3 N- N, }: }: ?$ z- v0 JB.抽象工厂模式(Abstract factory)5 C G' }% k% ]6 C/ B+ S# i! z+ w
C.单件模式(Singleton)
7 h6 t2 c1 F; ^. A/ X4 o) YD.代理模式(Proxy)
1 |# T [! }9 h* T' [; NE.状态模式(State)
' H8 g5 h0 _# |1 {5 p- C: D
$ O9 E1 R4 L$ c6 [- l, m
5 B3 z) Y/ o5 S* G6 }+ U5.借助继承,我们可以创建其他类的派生类。那么在PHP中,子类最多可以继承几个父类?
# X' n k; R y2 k1 J2 C7 N7 u% d2 e3 R* t6 [
A.1个( O; X: g$ S) l# `5 P6 u; {) }- Q# U, l
B.2个
4 K9 Y- Z0 z* }4 {% V/ g d9 ^C.取决于系统资源
5 B- F5 x, v6 x: j' D; I1 kD.3个
* E; H' X- T7 oE.想要几个有几个
~! |; h) z/ g- |
' ?( w9 Y. u# A4 Q5 ~+ X. l* u/ p9 q6 N5 e, a% I
6.以下脚本近似的表示了一种在PHP4中无法实现的特性,请问这个特性叫什么?-
- <?php
- class my_class
- {
- function my_funct ($my_param)
- {
- user_error ("Please define me", E_ERROR);
- }
- function b()
- {
- return 10;
- }
- }
- ?>
复制代码 A.多重继承
1 G( @0 h+ [$ zB.接口
( Y( f4 I' b0 `: zC.抽象方法% \1 D: A$ `! J3 k: p
D.Private方法! ?; a0 y' M) Z8 i. s1 ?; P
E.函数重载(function overloading)
m" P* X2 g4 y0 F9 G% S' w- d2 \% d& B' A# W8 s9 _
# E) L# T5 R! o* \7.假设定义了一个testclass类,它的构造函数的函数名是什么?
0 J( F. O$ [0 `, s y6 |
+ l$ y4 O+ V" h+ w, m& IA.__construct2 ]! q3 B- S6 A2 ^
B.initialize7 e' d) h3 V# s6 A9 y
C.testclass5 X5 V- S, B0 k9 q
D.__testclass6 F' Y' R7 Y1 B6 E7 m( j5 X
E.只有PHP5才支持构造函数
9 B. ~+ q. T: ~- v. {4 F# R8 W5 x' n; T+ i x
" X. t! j' a( F" J/ ^6 Z* j9 a
8.一个类如何覆盖默认的序列化机制?1 T4 `8 Z f; d8 y' o v% D2 t
1 m8 H% f/ Y9 v9 W# u5 p. jA.使用__shutdown和__startup方法$ e9 t" L& Z- I# [* \( Y1 t$ W
B.调用register_shutdown_function()函数0 g3 O/ X) @! y" Z, c! N" [
C.使用__sleep()和__wakeup()方法
# H7 n4 Q7 P1 X. t; Z1 e2 ID.无法覆盖默认序列化机制- Y8 m0 q0 |4 l/ Y
E.使用ob_start()将类放入输出缓冲中
3 a5 W. @ A+ ~2 ?6 N& }3 S2 ~; K$ O
/ Z0 g5 t& a9 J4 X4 @8 f/ r% ?% j" d; U1 G% q x
9.以下哪些面向对象的概念无法在PHP4中实现?5 h$ v8 U( e' b2 s Q( `. D
+ T7 z4 i9 Q% b/ F8 k@抽象类
$ O- \3 T2 E( u# Z@Final类
+ e9 G$ F9 `' e- i. j* u0 @& Y( C@Public、private、protected(PPP)方法7 }% F0 R' ~/ B/ {$ |
@接口* Z$ t" p1 q4 \, V1 `
* C5 g8 o. Y3 ^: N: ?0 x
A.抽象类
; O% M' ~8 O" m. a# |6 bB.PPP方法
0 c, S* Y# K% a2 D2 p- lC.PPP方法和接口
- _" k0 ]: s9 O+ ?D.以上所有都不可用7 F. u/ ~$ Q- @7 K! t
E.以上所有都可用
4 Q( v' i% E9 _) G
% V, k) {1 _& Y# y# X( K( L. Q% Z' Y
9 }0 c4 T' U- a/ j10.如何在类的内部调用mymethod方法?5 \' s3 S" H' |/ u9 G" }
; }. o5 ]# g2 G! \
A.$self=>mymethod();. s# P6 J7 p5 o0 Q e
B.$this->mymethod();% A0 V8 P8 S' o1 w5 p) m
C.$current->mymethod();
/ N; n# J( R- S: o* b0 ^D.$this::mymethod()
5 W6 ]! m- T+ U5 O' p2 K( i: o+ eE.以上都不对/ F* x, o! b7 z+ ^3 p
6 o4 a2 [* N) T% s) p3 z& F: t
- O# K* q$ y3 k5 N8 W% Q* L! |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) C5 R* l! L# Z# A3 ?
B.Null
0 W) O' x- l+ f" z" t, HC.Empty
- l! A! m9 \. s/ n yD.什么都没有
4 D7 a2 I A& C5 S2 ZE.一个错误# V2 L/ |, z% A) ?& F- \
) B8 X9 L! C( N% ]
! Y6 X" m) A' W# v12.以下脚本输出什么?-
- <?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$ @* Y% E& H& y( z6 ~' E
B.58 ]6 Q7 f N# _9 [: |/ K
C.2* k; E# _3 s4 {
D.Null- I' ^8 A5 `" D4 h
E.什么都没有
: K& H2 C# T9 W7 R6 s0 h( o: F6 _' g7 z' j# x* S% T
9 g6 F) A/ d. l; f
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
& ^' [( l+ ]* p! Z8 NB.10
3 `. U; [9 A9 p9 b* Y* K hC.什么都没有: e" o) G- Z- ~' M9 f3 m
D.构造函数将报错
2 d$ E" i' @8 _$ YE.5101 q1 `) ?. A0 X% L7 t
/ N! @2 W- b: L: Q1 Z: V& P T
, q Y; r/ \6 w
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函数必须返回一个值
5 Y* e# f2 [) M; S( H; ~; EB.reduce_fraction函数必须接受一个整型值
( |5 {3 A4 ^5 A3 j# `; I: M' xC.gcd函数有问题
$ N n6 w8 E. q) P! u# b0 mD.必须通过引用的方式传递$eight_tenths对象
) L+ d) m5 H3 vE.对象的实例不能传递给方法以外的其他结构。
, ~" Y4 \& ^3 g- K; d4 S
0 S5 O( g% \) U' _0 w
4 U+ A( d+ R2 i% C5 v3 A9 r15.以下代码是做什么的?-
- <?php
- require_once("myclass.php");
- myclass::mymethod();
- ?>
复制代码 A.静态调用mymethod方法 U- T4 ]! ]$ C- D7 d
B.生成myclass的实例并调用mymethod方法: y- \8 G# c4 m; d$ h9 L2 W
C.产生一个语法错误
8 ]1 W8 s5 F" q% Y* KD.默认myclass类最后被创建出的实例并调用mymethod()
0 A1 H; n/ y2 h9 F7 w5 wE.调用名为myclass::mymethod()的函数
( [4 t' B7 d: }7 C# }' w
* R$ [" X7 N$ ~# \. A. c [2 r6 ]; N3 n2 K; {* Y
16.PHP中有静态类变量吗?
4 m, w2 i* A% n9 P. ]0 O3 b% w) ?' Z& {8 H$ W/ V4 N8 b
A.有( k4 T* ^% `8 w. Y$ Z
B.没有# o( M! s. H3 [
; F8 y7 t5 R' v2 J, N$ x# {) ^/ o% o9 I
# F& ^& ^4 i/ c) s$ W17.以下脚本输出什么?-
- <?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. D- {, u9 B$ v1 ]
B.2
3 z% Z! L7 {1 A& c" dC.一个错误,因为没有定义a::$myvar" E3 x6 R5 w8 }6 P% u3 B
D.一个警告,因为没有定义a::$myvar, a2 o7 z9 X9 D4 N; m- D3 D6 \
E.什么都没有8 ]* u" r3 X$ D$ c, Q
6 a" W2 N+ i( w' U9 r
+ G9 o) }& S( P/ z18.如何即时加载一个类?" L7 t. D, J7 ]" J6 Y. q
* c* a9 J( o3 x G: Q$ b
A.使用__autoload魔术函数
9 b8 Q9 }) u* j. \0 _5 sB.把它们定义为forward类* F0 C6 v5 y6 d6 O! x# V- i/ Z; y
C.实现一个特殊的错误处理手段
, S" K9 G1 T$ u9 H0 k! r. A* y% CD.不可能0 o! r+ B& k w% m) n% V! g8 O
E.用有条件限制的include来包含它们
' ^* D4 v2 K4 `3 g3 K9 Q+ k4 W! R8 Y: @2 P* a
7 A# s/ o, z0 m8 [* Q
19.__________提供了一个高性能的解决面向对象中重复出现的问题的方案?
# |6 M8 Y" G; c1 U
% T* {9 O0 X2 u6 a! D; m 答案:__________& ^! M0 \$ N: Y: w- q ?2 u
" O7 X! M( o, ^& x m
4 |, q i2 n$ B7 f- y7 q( ]& f20.以下脚本输出什么?-
- <?php
- class a
- {
- function a()
- {
- echo 'Parent called';
- }
- }
- class b
- {
- function b()
- {
- }
- }
- $c = new b();
- ?>
复制代码 A.Parent called" ~5 n9 F% I0 V. y
B.一个错误- W7 }! Y9 z; U* E! y" ]
C.一个警告7 n. ]5 }1 k* a0 ?3 E
D.什么都没有
1 D5 V( ^3 n7 t8 @& @/ C. l
n8 w8 z& o0 n# R* q, U+ j& x- z- p' H1 }& E* X& N. U4 S" ]/ }
) `/ d+ }0 v @( |
答案速查
6 Q+ q# M; \' Z8 k4 m# O1.类2 S4 s8 Z0 ~+ @ i
2.BCD
$ Z# T$ I+ }9 l( h! V0 _/ R. _3.C
1 F& W/ R0 ^+ t$ a, ?' N4.C. t2 x' w, U% _, c% j% c/ k4 }% h
5.A) h @& L# D8 X7 m# _7 V* {
6.C
$ R2 M3 ^# \, ~. k, y, G! J% `" ]7.C2 T, W+ X, v9 t" K1 f, C9 R
8.C+ i! x% m: R1 d- ~( ^- m7 O
9.D5 e: e& d8 j1 L `4 [# m3 j; k/ c. j
10.B+ K2 x6 d" |* f
11.D# d; V$ A7 A' W# y2 s: f) Z. y2 u: b
12.B8 {! }" W9 c" K* Q. a; Z6 @: k
13.A+ W1 t D$ a! Q4 h: A8 X
14.D! S9 P; E% u, ?' h3 G& [8 `
15.A
% [: l, N' A. b% e7 W/ Y" @16.B
0 d% [' _( w. L! f' l3 x! t2 k4 t) L17.A1 N Z4 W1 Q0 b7 K: I8 h6 o
18.D
0 `; v; R/ @! w& W/ I# z0 t% j19.设计模式
; M0 ` [$ k3 q* q0 j J20.D
2 [% [. [% |3 U( V* t* n
; O3 O3 M7 ^0 x7 o; B7 t* G- d: E9 f! e
0 G" [5 @5 ? v/ y+ I' g* i答案详解
; Z- G; @& D9 H- z l* d
7 ~ G& s1 `4 V4 K1 I" |% G5 s1.类是对象的蓝图(对象是类的实例)。
; H, r) O6 n6 ?* H# {! Q
$ x' B8 \1 t) g6 Z3 E; k& J; v2.正确答案是B、C和D。set_value方法使用了错误的表达式$this->$my_value,因此该方法实际上是空的(这在PHP5里会导致一个错误,但在PHP4中不会。——译者注)。
. @6 z, E; `( Z" [% f; Z. L1 g: y* Q- N: \2 x
3.答案是C。PHP4中无法限制对类成员的访问,而在PHP5中则可以通过private关键字实现。: @( i# g9 j0 ?8 X
( f( [5 P0 @* [
4.单件模式可以限制一个类被实例化的次数。
! V1 K9 l, x) S, b1 i! t! c4 z- G0 T- S
5.尽管其他编程语言允许多重继承,但在PHP的对象模型中却不可以。因此答案是A。- b7 N! d( t9 u* ]2 s3 z
1 X& `/ x1 @/ |: i. T' S6.方框中的代码表现的是抽象方法(abstrace method)的实现。如果这个类继承自其他类,而my_funct方法在子类中被调用时没有覆盖,代码将抛出一个错误。虽然只是近似的实现了抽象方法,但在PHP4有限的对象模型中,这已经做得很好了。
7 L% K9 r! r ~9 ~. E
8 Q: ^6 E7 j+ |$ m! q7.PHP5有统一的构造函数(__construct()),但在PHP4中,构造函数就是和类有相同名称的方法。对于名为testclass的类,它的构造函数就是testclass()。答案是C。& X( F9 |% B ?, O
( Q9 ]( _$ u$ R9 K! L/ x8.__sleep()和__wakeup()能被用来自定义对象的序列化过程。正确答案是C。
0 b s7 i0 s% O
1 z) |9 \& F! u7 a9.PHP4中没有题目选项里所列的任何一个概念。答案是D。6 F8 @* }" b1 S, T
$ |& Y5 N5 R- ^% i
10.PHP中,在类的内部访问其成员和方法,要用$this这个特殊变量。因此答案是B。
# u' q) V1 O# _, j7 B# h' v% y1 E8 i( d
11.正确答案是D。my_class::_my_class()不是合法的构造函数(方法名的开头多了个_),因此脚本不会输出任何东西。你可能觉得这题是在考眼力而不是知识,是的,我们就是这么打算。仔细想想你就会同意——绝大多数的bug都是由错误的拼写造成的。这题并不是在戏弄你,而是考验你的排错能力。
# b5 u1 k) g4 V; j* {' A9 ^" I i' }8 H* P5 f- W
12.PHP4把对象视作标量进行处理,当$a赋给$b时,解释器创建对象的副本,因此对后一个对象的赋值不会影响到原先的对象。答案是B。但是要注意,PHP5里就不是这样处理的了(将会输出10)。: j" O" ]9 {/ {: C& ?0 ~
: k/ y4 s0 \" j) P2 X13.一上来,构造函数my_class通过引用,将自身存储在了变量$global_obj中。你可能会因此觉得,当我们后来吧$global_obj->my_value的值变为10时,$a也会相应改变。不幸的是,new操作符返回的不是引用,而是对象的副本。脚本输出5,答案是A。/ \9 R0 v: _5 Q
! N7 L( m q$ Q) z14.PHP中,把对象传递给函数或者方法时,默认传递的是值。这意味着通过参数传递给函数的对象,其实是对象的副本。这点导致了在函数或方法里对对象进行改动时,不会影响函数外的原先的那个对象。! @3 G. z/ z) V" s
回到第14题中,这就说明对象$eight_tenths从来没有被reduce_fraction函数改动过,而$fraction对象(参数)则被改动了。如果要在函数内部改动对象,就必须以引用的方式传递参数:
$ H0 X3 G$ r" W' W( T function reduce_fraction(&$fraction)6 M: {# W) e3 H
答案是D。
* K P9 U$ p$ j9 B0 p
" B M( r* V2 B; H6 {0 D- R15.题中所示的语法是用来进行静态调用的。当方法被静态调用时,它们就像一个独立的函数,与任何类的实例无关。答案是A。
2 I( B' f5 n- I# l1 O) [) q8 {( p% m% e9 O: s; G
16.没有。PHP4只允许声明静态函数变量,没有静态类变量。5 s5 l" i0 [' C- o
5 E3 s9 q" D Y8 ^) z
17.答案是A。类b的属性$myvar将在b的父类——类a调用构造函数时被定义,此外,像PHP4中的普通变量一样,定义类变量时也不需要给它赋值。类b在其父类调用构造函数之前就给$myvar赋了值,所以不管之后如何赋值,输出都是1。' N$ r% X' D" r' x
. X4 r; J O) y1 ^, a6 a
18.PHP4中无法即时装载类——它们必须在使用前就仔细声明好。PHP5中,可以使用__autoload魔术函数提醒解释器在找不到需要的类时尝试自动调用。因此答案是D。
3 F2 o) q- R: i! d! R' C; ^8 o$ I
% b: G. X. m* z19.为软件设计和编程中的常规问题提供良好的解决方案,这显然是在说设计模式。/ Y4 D! k! @7 a3 g) l7 f% H' Z# Z
& X5 S# |: s' f/ l20.脚本什么都不输出(答案是D)。因为子类的构造函数不会自动调用父类的构造函数。 |
|