O Princípio da Substituição de Liskov

By Tiago Frossard | 03/09/2009

Antes de continuarmos pelos padrões de projeto, acho importante ter aqui uma explicação sobre o Princípio da Substituição de Liskov. Ele é comum nas boas práticas de programação orientada a objetos e seus conceitos aparecem muito ao utilizar diversos padrões de projeto, principalmente no uso de Interfaces em padrões como o State (estado), o Strategy (Estratégia) ou os diversos tipos de Factories (Fábricas). Apesar de sua popularidade, ainda sim costuma dar um nó na cabeça de quem está começando.

Historicamente falando, O princípio foi introduzido em 1993 (muito recente, como podem ver) por Barbara Liskov e Jeannette Wing no artigo Family Values: A Behavioral Notion of Subtyping. Segundo ele:

Se q(x) é uma propriedade demonstrável dos objetos x de tipo T. Então q(y) deve ser verdadeiro para objetos y de tipo S onde S é um subtipo de T.

“Mas hein?!?” Apesar de parecer complicado, não é. Traduzindo isso para uma linguagem mais simples:

Se você pode chamar um método q de uma classe TMae, pode também chamar o método q de uma classe TFilha com herança de TMae.

“Bom, melhorou bastante. Mas você não pode explicar melhor não, Tiago?” Se uma classe herda de outra classe, cria-se a relação de “é um”. Explicar isso à fundo é material para um outro artigo, mas basta dizer que quando a classe TFilha herdou os métodos de TMae, ela passou a ser uma TMae estendida, melhorada (daí algumas linguagens utilizarem a palavra extends para definir herança): ela tem TUDO que uma TMae tem, além das coisas que só TFilha tem.

Se TFilha tem tudo que a TMae tem, as chamadas por TMae podem receber uma TFilha sem o menor problema. Entendamos o código abaixo:

Primeiro criamos uma classe TMae:

package Classes
{
	public class TMae
	{
		public function TMae()
		{
		}

		public function Voce(): void
		{
			trace ("Eu sou uma TMae");
		}
	}
}

Como TMae precisa de uma filha, vamos criá-la herdando de sua mãe:

package Classes
{
	import Classes.TMae;

	public class TFilha extends TMae
	{
		public function TFilha(): void
		{
			super(); // Chama o construtor da classe TMae
  		}

		public override function Voce():void
		{
			trace ("Eu sou uma TFilha");
		}

		public function Mae():void
		{
			// chama o método Voce() da classe mãe
			super.Voce();
		}
	}
}

Vale lembrar que TFilha pode ter seus extras, como fiz com o método Mae(), que exibe a mãe de filha, o método Voce() de super. Para colocar isso tudo para funcionar, precisamos da classe TMain:

package
{
	import flash.display.MovieClip;
	import Classes.TMae;
	import Classes.TFilha;

	public class TMain extends MovieClip
	{
		public function TMain(): void
		{
			var mae: TMae = new TMae();
			var filha: TFilha = new TFilha();

			trace ("======= MAE =======");
			this.testarLiskov(mae);

			trace ("======= FILHA =======");
			this.testarLiskov(filha);

			trace ("======= MAE DA FILHA =======");
			filha.Mae();

			//trace ("======= MAE DA MAE? =======");
			//mae.Mae();
		}

		public function testarLiskov(obj:TMae)
		{
			obj.Voce();
		}
	}
}

A saída disso é a seguinte:

	======= MAE =======
	Eu sou uma TMae
	======= FILHA =======
	Eu sou uma TFilha
	======= MAE DA FILHA =======
	Eu sou uma TMae

Para terminar, lembrem-se que o Princípio da Substituição de Liskov não é comutativo. Ou seja: podemos trocar a TMae por uma TFilha, mas não uma TFilha por uma TMae. Se TFilha pode possuir mais métodos e atributos  que TMae, não temos como chamá-los diretamente por TMae. Para confirmar, basta descomentar a linha mae.Mae() e ver que o compilador não consegue encontrar o método Mae() em TMae (claro, ele é de TFilha!).

Saiba mais sobre o Princípio na Wikipédia.

Artigos Relacionados:

Sem artigos relacionados.

4 Comments

  • By Everton Vieira, 03/09/2009 @ 21:46

    Mais um grande artigo Tiagão, o principio de Liskov, apesar de recente, é a base para muita coisa.
    Ficou muito bem explicado (y)

Links to this Post

  1. Tiago via Rec6 — 03/09/2009 @ 20:37

  2. Marios, Máquinas de Estados e o Padrão de Projetos State – Parte 2 | Nuss... E agora?!? — 27/09/2009 @ 21:34

  3. Padrão de Projetos Observer: Implementando mísseis teleguiados – parte 2 | Nuss... E agora?!? — 29/11/2009 @ 13:50

RSS feed for comments on this post. TrackBack URI

Leave a comment

WordPress Themes

Rec6plug

Search engine optimization by SEO Design Solutions