溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#forUnity快速入門(連載10)_C#里氏替換原則

發(fā)布時(shí)間:2020-06-10 22:46:01 來源:網(wǎng)絡(luò) 閱讀:540 作者:Liu_guozhu 欄目:開發(fā)技術(shù)

 C#forUnity編程語言快速入門教程(連載10)_C#OOP編程之里氏替換原則



    最近在Unity教學(xué)過程中,有學(xué)員對于C#的“里氏替換原則”(LSP)產(chǎn)生疑問表示不太理解。問題集中在不知道這個(gè)原則是做什么,有什么優(yōu)勢,具體在游戲開發(fā)(程序開發(fā))過程中有什么借鑒與指導(dǎo)作用。


    就以上問題我總結(jié)梳理一下,與大家共同探討。

    起源: 在我們的程序開發(fā)過程中,起初應(yīng)該都是以完成項(xiàng)目功能為重點(diǎn)。但是隨著軟件規(guī)模的不斷擴(kuò)大,人們發(fā)現(xiàn)只完成功能是遠(yuǎn)遠(yuǎn)不夠的。于是聰明的軟件工程師,從大量的編程實(shí)踐中開始總結(jié)一些共性的軟件開發(fā)理論,以供后人規(guī)范編程,更有效率、更穩(wěn)定的開發(fā)各種項(xiàng)目(包括游戲項(xiàng)目)。


   目前公認(rèn)的一些編程原則:

   1: 單一職責(zé)原則 英文名稱是Single Responsibility Principle,簡稱SRP
   2: 開閉原則 英文全稱是Open Close Principle,簡稱OCP

   3: 里氏替換原則 英文全稱是Liskov Substitution Principle,簡稱LSP
   4: 依賴倒置原則  英文全稱是Dependence Inversion Principle,簡稱DIP

  

    在以上編程開發(fā)原則中,“開閉原則”與“里氏替換原則”比較類似,都是研究如何在相對穩(wěn)定的編碼環(huán)境中,盡可能的允許程序功能的變化。也就是最低的編碼改動量,實(shí)現(xiàn)最大程度的軟件項(xiàng)目變化性,來適應(yīng)用戶對軟件系統(tǒng)不斷變化的功能要求。

 

    解釋如上概念:

    “開放-封閉原則”(即: 開閉原則)(OCP):   對于程序的擴(kuò)展是開放的(Open for extension),對于程序的修改是封閉的(Closed for modification)

    “里氏替換原則”:子類型必須能夠替換掉它們的父類型?。ǚ粗畡t不成立)


   “ 里氏替換”(也叫“里氏代換”原則)原則英文全稱是Liskov Substitution Principle,簡稱LSP。 由2008年圖靈獎得主、美國第一位計(jì)算機(jī)科學(xué)女博士Barbara Liskov教授和卡內(nèi)基·梅隆大學(xué)Jeannette Wing教授于1994年提出。 里氏替換原則就是要求寫程序前,先建立抽象,通過抽象建立規(guī)范,具體的實(shí)現(xiàn)在運(yùn)行時(shí)替換掉抽象,保證系統(tǒng)的高擴(kuò)展性、靈活性。


     “開閉原則”要求我們寫的程序修改盡量要少(即:封閉),但是對于功能的擴(kuò)展確實(shí)開放的、允許的。 這其實(shí)是提了一個(gè)很高的編程目標(biāo),很好的一個(gè)指導(dǎo)原則,但是如何具體到實(shí)現(xiàn)上,是沒有方法的,是不接“底氣”的。 所以“里氏替換”就給了一個(gè)具體的實(shí)現(xiàn)方法的原則,就是讓子類來無縫的對接父類,“子類型必須能夠替掉父類”。


    “里氏替換原則”具體的要求可以表述如下:

      1: 子類的所有方法必須在父類中聲明,或子類必須實(shí)現(xiàn)父類中聲明的所有方法。根據(jù)里氏替換原則,為了保證系統(tǒng)的擴(kuò)展性,在程序中通常使用父類來進(jìn)行定義,如果一個(gè)方法只存在子類中,在父類中不提供相應(yīng)的聲明,則無法在以父類定義的對象中使用該方法。
      
      2: 我們在運(yùn)用里氏替換原則時(shí),盡量把父類設(shè)計(jì)為抽象類或者接口,讓子類繼承父類或?qū)崿F(xiàn)父接口,并實(shí)現(xiàn)在父類中聲明的方法,運(yùn)行時(shí),子類實(shí)例替換父類實(shí)例,我們可以很方便地?cái)U(kuò)展系統(tǒng)的功能,同時(shí)無須修改原有子類的代碼,增加新的功能可以通過增加一個(gè)新的子類來實(shí)現(xiàn)。里氏替換原則其實(shí)就是“開閉原則”的具體實(shí)現(xiàn)手段之一!


     我們從序號為2的表述中可以看出,其實(shí)“里氏替換”原則就是一種更加具體的手段來實(shí)現(xiàn)“開閉原則”。 序號為2的理論其實(shí)就是我們常說的“動態(tài)多態(tài)性”的規(guī)則。


     針對以上理論,為了更好的理解,筆者給出“里氏替換原則”的實(shí)現(xiàn)參考代碼,供C#初學(xué)者進(jìn)行參考研究,有具體問題,可以留言,謝謝!


   //參考源碼1: 以下是使用“虛方法”,來實(shí)現(xiàn)“里氏替換”。

    class Person
    {
        //虛方法
        public virtual void SpeakLanguage()
        {
            Console.WriteLine("Person, 說話方法");
        }
    }
    
    class MrLiu:Person
    {
        //方法重寫
        public override void SpeakLanguage()
        {
            Console.WriteLine("MrLiu, 劉老師說中國話!");
        }
    }
    
    class Tom:Person
    {
        //方法重寫
        public override void SpeakLanguage()
        {
            Console.WriteLine("Tom, Tom Speak Engligh!");
        }
    }
    
    class Test
    {
        public static void Main()
        {
              /*  “里氏替換原則”(即:動態(tài)多態(tài)性)測試 */

              //功能的定義部分
              //Person per = new MrLiu();   //打印“MrLiu, 劉老師說中國話!”
              Person per = new Tom();        //打印“Tom, Tom Speak Engligh!”

              //功能的實(shí)現(xiàn)部分

              per.SpeakLanguage();
        }
    }



   //參考源碼2: 以下是使用“接口”,來實(shí)現(xiàn)“里氏替換”。

    interface ISpeakable
    {
        //抽象方法
        void SpeakLanguage();
    }
    
    class MrLiu:ISpeakable
    {
        //方法實(shí)現(xiàn)
        void ISpeakable.SpeakLanguage()
        {
            Console.WriteLine("MrLiu, 劉老師說中國話!");
        }
    }
    
    class Tom:ISpeakable
    {
        //方法實(shí)現(xiàn)
        void ISpeakable.SpeakLanguage()
        {
            Console.WriteLine("Tom, Tom Speak Engligh!");
        }
    }
    
    class Test
    {
        public static void Main()
        {
            /*  “里氏替換原則”(即:動態(tài)多態(tài)性)測試 */
            //功能的定義部分
            //ISpeakable Ispeak = new Tom();//打印“Tom, Tom Speak Engligh!”
            ISpeakable Ispeak = new MrLiu();//打印“MrLiu, 劉老師說中國話!”

            //功能的實(shí)現(xiàn)部分           
            Ispeak.SpeakLanguage();
        }
    }

   以上兩段代碼,分別用了父類“虛方法”與“接口”的方式分別實(shí)現(xiàn)“里氏替換”,當(dāng)然還可以用“抽象類”來實(shí)現(xiàn),究竟三者哪個(gè)方式,更應(yīng)該優(yōu)先使用呢? 現(xiàn)給出一個(gè)原則:


    “里氏替換”原則可以用以下方式來實(shí)現(xiàn):
    1> 虛方法的動態(tài)多態(tài)性。
    2> 抽象方法的動態(tài)多態(tài)性。
    3> 接口方法的動態(tài)多態(tài)性。


      規(guī)則: 實(shí)現(xiàn)“里氏替換”原則(動態(tài)多態(tài)性): 能用接口,不用抽象方法,能用抽象方法,不用虛方法。


    好了,針對以上問題,筆者就總結(jié)以上內(nèi)容,感興趣的C#編程愛好者可以進(jìn)行留言討論。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI