PHP面試常考內容之面向對象(3)

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.spla_utoload_register()提供了一種更加靈活的方式來實現類的自動加載,不再建議使用_autoload()函數
C.PHP在對象中調用一個不可訪問方法時,invoke()方法會被自動調用
D.匿名函數也叫閉包函數,常用作回調函數參數的值,但是不能作爲變量的值來使用
答案:B。
對於選項A,只有ArrayAccess能夠提供像訪問數組一樣訪問這個對象的接口,不能定義一個類或預定義接口Iterator去實現這個功能。所以,選項A錯誤。
對於選項B,因爲可以通過spla_utoload_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相關的面試知識、考題可以關注公衆號獲取:琉憶編程庫
圖片描述

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章