Sangguni

Prinsipyo ng Pagpapalit ng Liskov, pangatlong prinsipyo ng SOLID

Ang mga klase ng bata ay hindi dapat maapektuhan o baguhin ang les defimga pahayag ng uri ng parent class.

Ang konsepto ng prinsipyong ito ay ipinakilala ni Barbara Liskov sa isang pangunahing tono ng kumperensya noong 1987 at kalaunan ay inilathala sa isang papel kasama si Jannette Wing noong 1994. Ang kanilang defiorihinal na tion ay ang mga sumusunod:

Hayaan ang q (x) na isang maipapakita na pag-aari sa mga bagay x ng uri T. Kung gayon ang q (y) ay dapat na maipakita para sa mga bagay na y uri ng S kung saan ang S ay isang subtype ng T.

Nang maglaon, sa paglalathala ng mga SOLID na prinsipyo ni Robert C. Martin sa kanyang aklat na Agile Software Development, Principles, Patterns, and Practices at pagkatapos ay muling inilathala sa C# na bersyon ng aklat na Agile Principles, Patterns, and Practices sa C#, ang definaging kilala bilang Liskov substitution principle.

Dinadala tayo nito sa defiimpormasyong ibinigay ni Robert C. Martin: Ang mga subtyp ay dapat mapalitan ng kanilang mga pangunahing uri.

Mas simple, dapat i-override ng isang subclass ang mga pamamaraan ng magulang na klase sa isang paraan na hindi masisira ang pag-andar mula sa pananaw ng isang customer. Narito ang isang simpleng halimbawa upang maipakita ang konsepto.

klaseng Sasakyan {

    function startEngine () {

        // Default na pag-andar ng engine start

    }

 

    pagpapaandar mapabilis () {

        // Default na pagpapaandar ng pagpapabilis

    }

}

Dahil sa isang klase sa Sasakyan - maaari itong maging mahirap unawain - at dalawang pagpapatupad:

nagpapahaba ng sasakyan ang klase ng Kotse {

    function startEngine () {

        $ this-> pansinin ang ignisyon ();

        magulang :: startEngine ();

    }

 

    pribadong pag-andar ng pansinIgnisyon () {

        // Pamamaraan ng pag-aapoy

    }

}

 

pinalawak ng klase ng ElectricBus ang Sasakyan {

    pagpapaandar mapabilis () {

        $ this-> increaseVoltage ();

        $ this-> connectIndividualEngines ();

    }

 

    pribadong pag-andar pagtaasVoltage () {

        // Elektrikong lohika

    }

 

    connect ng pribadong pag-andarIndividualEngines () {

        // Logic ng koneksyon

    }

}

driver ng klase {

    function go (Sasakyan $ v) {

        $ v-> startEngine ();

        $ v-> mapabilis ();

    }

}

Ang isang klase ng kliyente ay dapat na maaaring gumamit ng pareho kung maaari itong gumamit ng Sasakyan.

Na nagdadala sa amin sa isang simpleng pagpapatupad ng Template ng Disenyo ng Paraan ng Template bilang ginamit namin ito sa OCP.

Maaari ka ring maging interesado sa pangalawang prinsipyo ng SOLID: https: //bloginnovazione.tl / open-closed-second-solid-principle / 3906 /

Batay sa aming dating karanasan sa Open / Closed na prinsipyo, maaari naming tapusin na ang prinsipyo ng pagpapalit ng Liskov ay malapit na nauugnay sa OCP. Sa katunayan, "ang isang paglabag sa LSP ay isang tagong paglabag sa OCP" (Robert C. Martin), at ang Template ng Disenyo ng Paraan ng Template ay isang klasikong halimbawa ng paggalang at pagpapatupad ng LSP, na kung saan ay isa sa mga solusyon upang sumunod din kasama ang OCP.

Halimbawa ng paglabag sa LSP

parihaba ng klase {

    pribadong $ topLeft;

    pribadong lapad ng $;

    pribadong $ taas;

 

    set ng pag-andar ng publiko ($ taas) {

        $ ito-> taas = $ taas;

    }

 

newsletter ng pagbabago
Huwag palampasin ang pinakamahalagang balita sa pagbabago. Mag-sign up upang matanggap ang mga ito sa pamamagitan ng email.

    pagpapaandar ng publiko getHeight () {

        ibalik ang $ ito-> taas;

    }

 

    pampublikong pagpapaandar setWidth ($ lapad) {

        $ ito-> lapad = $ lapad;

    }

 

    pampublikong pagpapaandar getWidth () {

        ibalik ang $ ito-> lapad;

    }

}

Magsimula tayo sa isang pangunahing hugis ng geometriko, isang rektanggulo. Ito ay isang simpleng object ng data na may mga setter at getter lamang para sa lapad at taas. Isipin na gumagana ang aming application at na-deploy na sa maraming mga kliyente. Ngayon kailangan nila ng isang bagong tampok. Dapat nilang mamanipula ang mga parisukat.

Sa totoong buhay, sa geometry, ang isang parisukat ay isang partikular na hugis ng isang rektanggulo. Kaya maaari naming subukang magpatupad ng isang klase sa Square na nagpapalawak ng isang klase ng Parihaba. Madalas sinasabing ang isang klase ng bata ay isang magulang na klase, at ang ekspresyong ito ay umaayon din sa LSP, kahit papaano sa unang tingin.

pinahaba ng class Square ang Parihaba {

    set ng pag-andar ng publiko ($ halaga) {

        $ ito-> lapad = $ halaga;

        $ ito-> taas = $ halaga;

    }

 

    pampublikong pagpapaandar setWidth ($ halaga) {

        $ ito-> lapad = $ halaga;

        $ ito-> taas = $ halaga;

    }

}

Ang isang parisukat ay isang rektanggulo na may pantay na lapad at taas at maaari kaming gumawa ng isang kakaibang pagpapatupad tulad ng sa nakaraang halimbawa. Maaari naming i-override ang parehong mga setter upang maitakda ang parehong taas at lapad. Ngunit paano ito makakaapekto sa code ng client?

kliyente sa klase {

    function areaVerifier (Parihaba $ r) {

        $ ----------------> setWidth (5);

        $ ----------------> setHeight (4);

        kung ($ ----------------> lugar ()! = 20) {

            magtapon ng bagong Exception ('Masamang lugar!');

        }

        bumalik totoo;

    }

}

Maiisip na magkaroon ng isang klase ng kliyente na sumusuri sa lugar ng parihaba at nagtatapon ng isang pagbubukod kung ito ay mali.

lugar ng pag-andar () {

    ibalik ang $ ito-> lapad * $ ito-> taas;

}

Malinaw na naidagdag namin ang pamamaraan sa itaas sa aming klase ng Parihaba upang maibigay ang lugar.

pinalawak ng klase LspTest ang PHPUnit_Framework_TestCase {

    test testRectangleArea () {

        $ r = bagong Rectangle ();

        $ c = bagong Client ();

        $ this-> assertTrue ($ c-> areaVerifier ($ r));

    }

}

At gumawa kami ng simpleng pagsubok sa pamamagitan ng pagpapadala ng blangko na rectangle object sa area checker at pumasa ang pagsubok. Kung ang klase namin ay Square definatapos nang tama, ang pagpapadala nito sa Client's areaVerifier() ay hindi dapat masira ang functionality nito. Pagkatapos ng lahat, ang isang parisukat ay isang parihaba sa bawat kahulugan ng matematika. Pero class natin?

test testSquareArea () {

    $ r = bagong Square ();

    $ c = bagong Client ();

    $ this-> assertTrue ($ c-> areaVerifier ($ r));

}

Kaya, ang aming Square class ay hindi isang Rectangle kung tutuusin. Nilalabag nito ang mga batas ng geometry. Nabigo ito at lumalabag sa prinsipyo ng pagpapalit ng Liskov.

Ercole Palmeri

newsletter ng pagbabago
Huwag palampasin ang pinakamahalagang balita sa pagbabago. Mag-sign up upang matanggap ang mga ito sa pamamagitan ng email.

Kamakailang Mga Artikulo

Green and Digital Revolution: Kung Paano Binabago ng Predictive Maintenance ang Industriya ng Langis at Gas

Binabago ng predictive maintenance ang sektor ng langis at gas, na may makabago at proactive na diskarte sa pamamahala ng halaman.…

Abril 22 2024

Itinaas ng UK antitrust regulator ang BigTech alarm sa GenAI

Ang UK CMA ay naglabas ng babala tungkol sa gawi ng Big Tech sa merkado ng artificial intelligence. doon…

Abril 18 2024

Casa Green: rebolusyon ng enerhiya para sa isang napapanatiling hinaharap sa Italya

Ang "Case Green" Decree, na binuo ng European Union upang mapahusay ang kahusayan ng enerhiya ng mga gusali, ay nagtapos sa proseso ng pambatasan nito sa…

Abril 18 2024

Ecommerce sa Italy sa +27% ayon sa bagong Ulat ni Casaleggio Associati

Iniharap ang taunang ulat ng Casaleggio Associati sa Ecommerce sa Italy. Ulat na pinamagatang “AI-Commerce: the frontiers of Ecommerce with Artificial Intelligence”.…

Abril 17 2024