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

Ang Mga Benepisyo ng Mga Pangkulay na Pahina para sa mga Bata - isang mundo ng mahika para sa lahat ng edad

Ang pagbuo ng mahusay na mga kasanayan sa motor sa pamamagitan ng pangkulay ay naghahanda sa mga bata para sa mas kumplikadong mga kasanayan tulad ng pagsusulat. Kulayan…

2 Mayo 2024

Narito na ang Hinaharap: Paano Binabago ng Industriya ng Pagpapadala ang Global Economy

Ang sektor ng hukbong-dagat ay isang tunay na pandaigdigang pang-ekonomiyang kapangyarihan, na nag-navigate patungo sa isang 150 bilyong merkado...

1 Mayo 2024

Pumirma ang mga publisher at OpenAI ng mga kasunduan para i-regulate ang daloy ng impormasyong pinoproseso ng Artificial Intelligence

Noong nakaraang Lunes, inihayag ng Financial Times ang isang deal sa OpenAI. Nilisensyahan ng FT ang world-class na pamamahayag nito...

Abril 30 2024

Mga Online na Pagbabayad: Narito Kung Paano Ka Binabayaran ng Mga Serbisyo ng Streaming Magpakailanman

Milyun-milyong tao ang nagbabayad para sa mga serbisyo ng streaming, na nagbabayad ng buwanang bayad sa subscription. Karaniwang opinyon na ikaw ay…

Abril 29 2024