Tutorial

Principio de substitución de Liskov, terceiro principio SÓLIDO

As clases infantís nunca deberían afectar nin modificar os ficheiros defideclaracións do tipo da clase pai.

O concepto deste principio foi introducido por Barbara Liskov nunha conferencia maxistral de 1987 e posteriormente publicado nun artigo xunto con Jannette Wing en 1994. defición orixinal é a seguinte:

Sexa q (x) unha propiedade demostrable en obxectos x de tipo T. Entón q (y) debería ser demostrable para obxectos y de tipo S onde S é un subtipo de T.

Posteriormente, coa publicación dos principios SOLID de Robert C. Martin no seu libro Agile Software Development, Principles, Patterns, and Practices e despois republicados na versión C# do libro Agile Principles, Patterns, and Practices en C#, o deficoñecíase como principio de substitución de Liskov.

Isto lévanos ao defiinformación dada por Robert C. Martin: Os subtipos deben ser substituíbles polos seus tipos de base.

Máis sinxelamente, unha subclase tería que substituír os métodos da clase pai dun xeito que non rompe a funcionalidade desde o punto de vista dun cliente. Aquí tes un exemplo sinxelo para demostrar o concepto.

clase Vehículo {

    función startEngine () {

        // Funcionalidade de arranque predeterminada do motor

    }

 

    función accelerate () {

        // Funcionalidade de aceleración predeterminada

    }

}

Dada unha clase de vehículo (pode ser abstracta) e dúas implementacións:

clase Car estende Vehículo {

    función startEngine () {

        $ this-> engageIgnition ();

        pai :: inicioEngine ();

    }

 

    función privada engageIgnition () {

        // Procedemento de ignición

    }

}

 

clase ElectricBus amplía o vehículo {

    función accelerate () {

        $ this-> increaseVoltage ();

        $ this-> connectIndividualEngines ();

    }

 

    función privada incrementarVoltaxe () {

        // Lóxica eléctrica

    }

 

    función privada connectIndividualEngines () {

        // Lóxica de conexión

    }

}

condutor de clase {

    function go (Vehículo $ v) {

        $ v-> startEngine ();

        $ v-> accelerate ();

    }

}

Unha clase cliente debería poder usar ambas as dúas se pode usar Vehicle.

O que nos leva a unha implementación sinxela do Patrón de Deseño de Métodos de Modelo tal e como o empregamos no OCP.

Tamén che pode interesar o segundo principio SOLID: https: //bloginnovazione.gl / principio-segundo-solido-aberto-pechado / 3906 /

Baseado na nosa experiencia previa co principio Aberto / Pechado, podemos concluír que o principio de substitución de Liskov está intimamente relacionado co OCP. De feito, "unha violación de LSP é unha violación latente de OCP" (Robert C. Martin), e o Patrón de deseño de métodos de modelo é un exemplo clásico de respecto e implementación de LSP, que á súa vez é unha das solucións para cumprir tamén con OCP.

Exemplo de violación de LSP

clase Rectángulo {

    privado $ topEsquerda;

    $ ancho privado;

    $ altura privada;

 

    función pública setHeight ($ height) {

        $ this-> height = $ height;

    }

 

Boletín de innovación
Non te perdas as novidades máis importantes sobre innovación. Rexístrese para recibilos por correo electrónico.

    función pública getHeight () {

        devolver $ esta-> altura;

    }

 

    función pública setWidth ($ width) {

        $ this-> width = $ width;

    }

 

    función pública getWidth () {

        devolve $ este-> ancho;

    }

}

Comecemos cunha forma xeométrica básica, un rectángulo. É só un sinxelo obxecto de datos con axustes e obtencións de ancho e alto. Imaxina que a nosa aplicación funciona e xa está implantada en varios clientes. Agora necesitan unha nova función. Deben ser capaces de manipular cadrados.

Na vida real, en xeometría, un cadrado é unha forma particular dun rectángulo. Polo tanto, poderiamos intentar implementar unha clase Square que estenda unha clase Rectangle. A miúdo dise que unha clase infantil é unha clase principal e esta expresión tamén se axusta a LSP, polo menos a primeira vista.

clase cadrado estende Rectángulo {

    función pública setHeight (valor $) {

        $ this-> width = $ value;

        $ this-> height = $ value;

    }

 

    función pública setWidth ($ value) {

        $ this-> width = $ value;

        $ this-> height = $ value;

    }

}

Un cadrado é un rectángulo con ancho e altura iguais e poderiamos facer unha implementación estraña como no exemplo anterior. Poderiamos anular os dous axustadores para establecer a altura e a anchura. Pero, como afectará isto ao código do cliente?

Cliente de clase {

    función areaVerifier (Rectángulo $ r) {

        $ r-> setWidth (5);

        $ r-> setHeight (4);

        if ($ r-> area ()! = 20) {

            lanza unha nova excepción ("¡Área mala!");

        }

        volver certo;

    }

}

É concebible ter unha clase de cliente que comprobe a área do rectángulo e lanza unha excepción se está mal.

área de función () {

    devolver $ this-> width * $ this-> height;

}

Obviamente engadimos o método anterior á nosa clase de Rectángulo para proporcionar a área.

clase LspTest estende PHPUnit_Framework_TestCase {

    función testRectangleArea () {

        $ r = novo rectángulo ();

        $ c = novo cliente ();

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

    }

}

E creamos unha proba sinxela enviando un obxecto rectángulo en branco ao verificador de área e a proba pasa. Se a nosa praza de clase é deficorrectamente, envialo ao areaVerifier() do Cliente non debería romper a súa funcionalidade. Despois de todo, un cadrado é un rectángulo en todos os sentidos matemáticos. Pero é a nosa clase?

función testSquareArea () {

    $ r = novo cadrado ();

    $ c = novo cliente ();

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

}

Entón, a nosa clase Square non é un Rectángulo despois de todo. Incumpre as leis da xeometría. Falla e viola o principio de substitución de Liskov.

Ercole Palmeri

Boletín de innovación
Non te perdas as novidades máis importantes sobre innovación. Rexístrese para recibilos por correo electrónico.

Artigos recentes

Os beneficios das páxinas para colorear para nenos: un mundo de maxia para todas as idades

O desenvolvemento da motricidade fina a través da cor prepara aos nenos para habilidades máis complexas como escribir. Para colorear…

2 maio 2024

O futuro está aquí: como a industria do transporte marítimo está revolucionando a economía global

O sector naval é unha verdadeira potencia económica mundial, que navega cara a un mercado de 150 millóns...

1 maio 2024

Editores e OpenAI asinan acordos para regular o fluxo de información procesada pola Intelixencia Artificial

O pasado luns, o Financial Times anunciou un acordo con OpenAI. FT licencia o seu xornalismo de clase mundial...

Abril 30 2024

Pagos en liña: aquí tes como os servizos de streaming che fan pagar para sempre

Millóns de persoas pagan por servizos de streaming, pagando taxas de subscrición mensuais. É unha opinión común que vostede...

Abril 29 2024