PHP面試常考內容之物件導向(3)

weixin_33806914發表於2019-02-14

PHP面試專欄正式起更,每週一、三、五更新,提供最好最優質的PHP面試內容。
繼上一篇“PHP面試常考內容之物件導向(2)”發表後,今天更新物件導向的最後一篇(3)。需要(1),(2)的可以直接點文字跳轉獲取。
PHP面試常考內容之物件導向(1)
整個物件導向文章的結構涉及的內容模組有:

一、物件導向與程式導向有什麼區別?
二、物件導向有什麼特徵?
三、什麼是建構函式和解構函式?
四、物件導向的作用域範圍有哪幾種?
五、PHP 中魔術方法有哪些?
六、什麼是物件克隆?
七、this、self和parent的區別是什麼?
八、抽象類與介面有什麼區別與聯絡?
九、PHP物件導向的常考面試題講解

關於PHP物件導向的內容將會被分為三篇文章進行講解完整塊內容,第一篇主要講解一到四點內容,第二篇主要講解五到八的內容,第三篇圍繞第九點進行講解。


以下正文的內容都來自《PHP程式設計師面試筆試真題解析》書籍,如果轉載請保留出處:


九、PHP物件導向的常考面試題講解

【真題1】 什麼是物件導向?其主要特徵是什麼?

答案:物件導向是程式的一種設計方式,它是一種對現實世界的理解和抽象的方法,它可以提高程式的重用性,讓程式結構更加清晰。
物件導向的主要特徵為:封裝、繼承、多型。


【真題2】 可以獲得物件的類名的函式是( )。

A.get_class_name B.get_class C.class_exists D.get_class_vars
答案:B。
PHP中獲取物件的類名函式是get_class()。所以,選項B正確。
對於選項A,不存在該方法。所以,選項A錯誤。
對於選項C,class_exists()函式可以檢查類是否存在。所以,選項C錯誤。
對於選項D,get_class_vars()函式可以獲取類的預設屬性。所以,選項D錯誤。
所以,本題的答案是B。


【真題3】 請簡單說明PHP的垃圾收集機制。

答案:在PHP中,當沒有任何變數指向該物件時,該物件變為垃圾將會在記憶體中被銷燬,可以防止記憶體溢位。記憶體中對變數有引用計數,當計數到0時變數被銷燬。


【真題4】多型與方法重寫有什麼關係?

答案:多型是指一個類可以被多個類繼承,每個子類都可以對父類方法進行重寫,每個類裡的同名方法可以實現不同的功能從而表現出多種形態,它增強了軟體的靈活性和重用性。
重寫是子類對父類中的方法進行改寫。它們的關係是重寫讓類具備多型性。


【真題5】物件導向幾大原則是什麼?

答案:物件導向存在五大基本原則,分別是:單一職責原則、開放封閉原則、替換原則、依賴原則、介面分離原則等。
(1)單一職責原則
所謂單一職責原則,即一個類最好只做一件事。為了提高內聚性減少引起變化,單一原則是低耦合、高內聚的面向原則上的引申。
(2)開放封閉原則
軟體的功能應該是可擴充套件的,儘可能減少修改,因為修改程式,可能會對原來的程式造成影響。雖然建議儘可能不修改程式,但是允許通過新增功能來減少修改。
(3)替換原則
只有子類能夠替換基類,在繼承機制的約束規範中,子類替換基類時,可以保證執行期內識別子類,保證繼承複用。
(4)依賴倒置原則
高層模組不依賴底層模組,二者都依賴於抽象,抽象不依賴於實體,而實體依賴於抽象。模組間的依賴是通過抽象方法發生的,實現類中不發生直接的依賴關係,而依賴關係是通過介面或抽象類產生的。即介面或抽象類不依賴於實現類,而實現類依賴於介面和抽象類。這種依賴倒置原則可以有效地減少類之間的耦合性,提高系統的穩定性,減少併發引起的風險,提高程式碼的可讀性和可維護性。
(5)介面隔離原則
建議開發使用多個小的、專門的介面,避免使用一個大的總介面。即每一個功能有一個專門的功能介面,需要用到才呼叫,不需要全部功能彙總到一個介面,這樣可以提高程式碼的靈活性,降低類之間的耦合性,提高穩定性。


【真題6】以下有關PHP高階特性的說法中,正確的是( )。

A.可以定義一個類去實現預定義介面Iterator,然後就能像訪問陣列一樣訪問這個類建立的物件
B.spl_autoload_register()提供了一種更加靈活的方式來實現類的自動載入,不再建議使用_autoload()函式
C.PHP在物件中呼叫一個不可訪問方法時,invoke()方法會被自動呼叫
D.匿名函式也叫閉包函式,常用作回撥函式引數的值,但是不能作為變數的值來使用
答案:B。
對於選項A,只有ArrayAccess能夠提供像訪問陣列一樣訪問這個物件的介面,不能定義一個類或預定義介面Iterator去實現這個功能。所以,選項A錯誤。
對於選項B,因為可以通過spl_autoload_register()函式建立autoload函式的佇列,按定義順序逐個執行,比_autoload()函式只可以定義一次使用更方便,所以不建議使用_autoload()函式。所以,選項B正確。
對於選項C,_call方法是在建立一個類例項化後就可以直接呼叫物件使用,當呼叫的方法不可訪問或沒有許可權訪問時,會自動呼叫_call方法。所以,選項C錯誤。
對於選項D,匿名函式是可以賦值給變數的。所以,選項D錯誤。
所以,本題的答案是B。


【真題7】__autoload()函式的工作原理是什麼?

答案:使用這個魔術函式的基本條件是,類檔案的檔名要和類的名字保持一致。
當程式執行到例項化某個類時,如果在例項化前沒有引入這個類檔案,那麼就自動執行__autoload()函式。這個函式根據例項化的類名去查詢這個類的路徑,一旦找到這個類後就會通過執行include或require載入該類,從而保證程式能夠繼續執行。如果沒有找到,那麼報錯。


【真題8】以下關於PHP名稱空間的說法中,不正確的是( )。

A.訪問任意全域性類、函式或常量,都可以使用完全限定名稱,例如strlen()或Exception或INI_ALL
B.關鍵字 namespace可用來顯式訪問當前名稱空間或子名稱空間中的元素,它等價於類中的 this 操作符
C.任意合法的PHP程式碼都可以包含在名稱空間中,但只有三種型別的程式碼受名稱空間的影響,它們是類、函式和常量
D.常量__NAMESPACE__的值是當前名稱空間名稱的字串。如果是在全域性中,那麼它不包括任何名稱空間中的程式碼,本身是一個空字串
答案:B。
namespace關鍵字是用來宣告名稱空間用的,它並不能等價於this操作符的功能。所以,選項B說法不對。
所以,本題的答案是B。

【真題9】以下程式碼的執行結果是( )。

<?php    
    class Person{
       var $name;
    }
    $a = new Person();
    $a->name = "張三";
    $b = $a;
    $b->name = "李四";
    echo $a->name;
?>

A.張三 B.李四 C.Null D.什麼都沒有
答案:B。
首先$a例項化Person類,把張三賦值給類內的變數name,把物件張三的值給了$b,通過$b去修改類內name的值為李四,所以最後輸出Person類內的name,輸出得到結果李四。所以,選項B正確,選項A、選項C、選項D錯誤。
所以,本題的答案是B。


【真題10】下面說法錯誤的是( )。

A.如果一個類的成員前面有訪問修飾符private,那麼這些成員不能被繼承,在類的外部不可見。但如果成員被指定為protected和public,那麼可以被繼承,在類的外部也是可見的
B.PHP5中,final關鍵字可以禁止繼承和過載
C.PHP5中,解構函式的名稱是__destruct(),並且不能有任何引數
D.繼承介面的類必須實現介面中宣告的所有方法,在PHP中,如果繼承介面的類沒有實現介面中的方法,那麼將會產生一個致命錯誤
答案:A。
對於選項A,private修飾的成員是不可以被繼承的,protected的成員是可以被繼承的,但是在外部不可見,選項A說法錯誤,所以,選項A正確。
對於選項B,final關鍵字的方法是禁止被繼承和過載的,選項B說法正確,所以選項B錯誤。
對於選項C,解構函式不能有引數,選項C說法正確,所以,選項C錯誤。
對於選項D,繼承介面的類沒有實現介面中的方法是會產生錯誤的,選項D說法正確,所以,選項D錯誤。
所以,本題的答案是A。


自己整理了一篇“個人程式設計6年的心得——如何學好程式設計?”的文章,關注公眾號:“琉憶程式設計庫”,回覆:“學好”,我發給你。

【真題11】 定義類成員的訪問許可權控制符有哪些?預設修飾符是什麼?

答案:類成員的訪問修飾符有public、private、protected,主要用來修飾類中的成員屬性和方法。public是公共型別,允許在類的內部或子類中使用,也可以在類外部被訪問。private是私有型別,只能在類的內部被使用,不能被繼承使用。protected是保護型別,只能在類的內部或子類中使用。如果不使用public、private、protected等關鍵字修飾方法或屬性,那麼可以使用var關鍵字,它的功能等同於public,可以在類內或類外被呼叫,也可以被繼承使用。
其中,PHP預設的修飾符是public,即公有型別。
類前面只能加final、abstract關鍵字,被final修飾的屬性或方法是不能被繼承的,只能在當前類中使用,abstract定義的類或方法,叫作抽象類或抽象方法。
屬性前面:必須有訪問修飾符(private,protected,public,var)。


【真題12】 PHP的魔術方法包含哪些(越多越好)?在什麼情況下被自動呼叫?

答案:PHP可用的魔術方法會在特定情況下被自動呼叫,但是前提是特定的條件被觸發,並且這些魔術方法可以在類中作為方法。
PHP的魔術方法有:
1)_construct():建構函式,建立物件時自動被呼叫。
2)_destruct():解構函式,物件的所有引用都被刪除或者當物件被顯式銷燬時執行。
3)__clone():克隆函式,呼叫clone方法時自動呼叫。
4)__set():當程式試圖寫入一個不存在或不可見的成員變數時自動呼叫。該函式在類中定義時必須有兩個引數:變數名和變數值。
5)__get():當程式呼叫一個未定義或不可見的成員變數時自動呼叫__get()來讀取變數值。定義時必有有一個引數:變數名。
6)__call():當程式試圖呼叫不存在或不可見的成員方法時,自動呼叫__call()。__call()方法一般用於監視錯誤的方法呼叫。為了避免當呼叫的方法不存在時產生錯誤,可以使用__call()方法來避免。該方法包含兩個引數:方法名和方法引數。其中,方法引數以陣列形式存在。
7)__sleep():使用serialize()實現序列化物件時,先呼叫該方法,可以用來清除物件並返回一個該物件中所有變數的陣列。
8)__wakeup():使用unserialize()還原一個被序列化的物件時,先執行該方法,恢復在序列化中可能丟失的資料庫連線及相關工作。
9)__toString():當使用echo或print輸出物件時,將物件轉化為字串。
10)__autoload():呼叫未被例項化的類時,自動呼叫,在指定路徑下查詢和該類名稱相同的檔案。


【真題13】 $this、self和parent這三個關鍵詞分別代表什麼?在哪些場合下使用?

答案:$this表示當前物件,在當前類中可以通過->符呼叫類內的屬性和方法。
self表示當前類,只能通過self的形式(“self::方法或屬性”)呼叫類內的方法。
parent表示當前類的父類,呼叫父類內的方法只能使用“parent::”形式呼叫。

【真題14】下面關於物件導向的描述中,錯誤的是( )。

A.父類的建構函式與解構函式不會自動被呼叫
B.成員變數需要用public、protected、private修飾,在定義變數時不再需要var關鍵字
C.父類中定義的靜態成員,不可以在子類中直接呼叫
D.包含抽象方法的類必須為抽象類,抽象類不能被例項化
答案:A。
對於選項A,子類繼承父類,如果子類沒有建構函式和解構函式,那麼例項化子類時會自動呼叫父類的建構函式和解構函式;但如果子類只有建構函式沒有解構函式時,那麼例項化子類時,自動呼叫的是子類的建構函式,銷燬物件時呼叫父類的解構函式;如果子類沒有建構函式只有解構函式,那麼例項化子類時會自動呼叫父類的建構函式,銷燬物件時呼叫子類的解構函式,選項A說法不完全。所以,選項A正確。
對於選項B,成員變數使用了public、protected、private修飾定義變數時是不需要var關鍵字的,選項B說法正確。所以,選項B錯誤。
對於選項C,父類中的靜態成員,子類中是不可以直接訪問的,選項B說法正確。所以,選項C錯誤。
對於選項D,一個包含抽象方法的類必須是抽象類,並且抽象類不能被例項化。選項D說法正確。所以,選項D錯誤。
所以,本題的答案是A。


【真題15】 在PHP中,如果派生類與父類有相同名字的函式,那麼派生類的函式會替換父類的函式,有如下程式程式碼:

<?php
    class A {
          function disName(){
            echo "Picachu";
      }
    }
    class B extends A {
       var $tmp='';
       function disName(){
          echo "Doraemon";
       }
    }
    $cartoon = new B;
    $cartoon->disName();
?>

上述程式碼的執行結果為( )。
A.tmp B.Picachu C.disName
D.Doraemon E.無輸出
答案:D。
當派生類繼承父類時,如果通過例項化一個派生類的物件來訪問物件的方法時,派生類不存在父類中的方法,那麼執行父類中的方法。如果派生類和父類存在相同名字的方法,那麼派生類的方法會覆蓋父類方法,執行派生類的方法。所以,本題中可以執行派生類的disName()方法。所以,選項D正確,選項A、選項B、選項C、選項E錯誤。
所以,本題的答案是D。


【真題16】什麼是抽象類和介面?抽象類和介面有什麼不同和相似的地方?

答案:被關鍵字abstract修飾的類叫作抽象類,抽象類是不能被例項化的。被abstract修飾的方法為抽象方法,一個類只要有一個抽象方法,這個類一定是抽象類。
介面是通過關鍵字interface來定義的,可以指定某個類必須實現哪些方法,但不需要定義這些方法的具體實現。PHP類只支援是單重繼承的,但通過介面可以實現PHP類的多重繼承。
抽象類和介面的不同和相似的地方如下所示。
1)抽象類是一種不能被例項化的類,只能作為其他類的父類來使用。
2)抽象類是通過關鍵字abstract來宣告的。
3)抽象類與普通類相似,都包含成員變數和成員方法,兩者的區別在於,抽象類中至少要包含一個抽象方法。
4)抽象方法沒有方法體,該方法就是要被子類重寫的。
5)抽象方法的格式為:abstract function abstractMethod()。
6)因為PHP中只支援單重繼承,所以如果想實現多重繼承,那麼就要使用介面。也就是說,子類可以實現多個介面。
7)介面類是通過interface關鍵字來宣告的,介面類中的成員變數和方法都是public的,可以不用顯式地使用public來修飾。
8)介面中的方法沒有方法體。介面中的方法就是要被子類繼承實現的。
9)子類繼承抽象類使用extends關鍵字,子類實現介面使用implements關鍵字。


【真題17】用類程式設計實現:Stu類中有兩個私有屬性name和sex,有兩個公有方法,setName()和setSex()引數自定,方法可實現對兩個私有屬性進行修改。在例項化類時要求對私有屬效能初始化。

答案:實現程式碼如下:

<?php
    Class Stu{
       private $name;
       private $sex;
       public function setName($name){
          $this->name = $name;
       }
       public function setSex($sex){
          $this->sex = $sex;
       }
    }
?>


【真題18】 假如有一個類Person,例項化(new)一個物件$p,那麼以下使用物件$p呼叫Person類中的getInfo方法的寫法中,正確的是( )。

A.$p=>getInfo(); B.$this->getInfo();
C.$p->getInfo(); D.$p::getInfo();
參考答案:C。
分析:“::”主要用於訪問類中的靜態成員,“->”主要用於訪問類中的變數和方法,“=>”主要應用在陣列中的key和value對映時使用。所以,選項A、選項B、選項D錯誤,選項C正確。


【真題19】php中public、protected、private三種訪問控制模式的區別是什麼?

參考答案:php中public、protected、private三種訪問控制模式的區別如下:
訪 問 模 式 描 述
public 共有,任何地方都可以訪問
protected 繼承,只能在本類或子類中訪問,在其他地方不能使用
private 私有,只能在本類中訪問,在其他地方不能使用


【真題20】 在PHP物件導向中,下面關於final修飾符的描述中,錯誤的是( )。

A.使用final標識的類不能被繼承
B.在類中使用final標識的成員方法,在子類中不能被覆蓋
C.不能使用final標識成員屬性
D.使用final標識的成員屬性,不能在子類中再次定義
參考答案:D。
分析:因為final只能修飾類與方法,不能修飾類的屬性。所以,選項D錯誤。

PS:由於真題較多,僅羅列PHP物件導向筆試中經常遇到的20道考題!


至此本週(2019-2-11 至 2019-2-15 的物件導向專題已更新完畢,以上的內容只是摘取了PHP物件導向中最常考的內容,個別內容沒有羅列可以從原書中獲取。)感謝大家的支援!

預告:下週(2019-2.18 —— 2.22)更新“PHP面試常考內容之Memcache和Redis快取的”專題,敬請期待。

以上內容摘自《PHP程式設計師面試筆試真題解析》書籍,該書已在天貓京東噹噹等電商平臺銷售。
圖片描述

更多PHP相關的面試知識、考題可以關注公眾號獲取:琉憶程式設計庫
圖片描述

對本文有什麼問題或建議都可以進行留言,將不斷完善追求極致,感謝你們的支援。

相關文章