Generalização Especialização Herança
Postado por Carlos Fernando Sylverio | Postado em Orientação a Objetos, Programação, UML | Postado em 29-01-2009
0
Olá pessoal, estive de férias e passei um bom tempo sem escrever, mas agora descançado, não há mais desculpas.
Fiz uma breve descrição sobre generalização, especialização e herança, devido a um pedido do último post e montei um pequena aplicação para exemplificar o assunto.
Conceito
Podemos dizer que generalização é o agrupamento de objetos ou elementos com características comuns em um modelo ou sistemas, é uma descrição mais geral sobre o objeto referente.
E a especialização é processo inverso, é a definição das particularidades de cada objeto ou elemento, são elementos mais consistentes que estendem o elemento genérico.
Dando continuidade ao exemplo citado no último post, casa, galpão, prédio, chamarei a generalização de “Habitação“.
(achei que não foi uma boa escolha esses elementos, prédio, galpão, etc… Para falar de generalização, mas vou utilizá-los para não confundir quem está começando a ver O.O., e manter um pouco de compatibilidade com o post anterior)
Ou seja, todos os elementos, são habitações, porém cada elemento guarda sua característica particular.
O que se ganha com isso?
A utilização de generalização tem dois propósitos:
- Permitir que a classe base ou subclasse ser usada como variável. E regra é que uma instância da subclasse possa ser usada quando a superclasse é declarada. Com isso possibilitamos a realização de operações polimórficas.
- Permitir a incrementar as características de um elemento pelas características comuns de seu antecessor. Esta é a chamada de herança.
br>
Herança é a definição da implementação da generalização no código
Já li em alguns livros que o conceito de generalização pode ser utilizada para agrupar características comuns de cada objeto, passando os atributos comuns para o objeto mais genérico. Mas eu discordo desta opinião.
Não há nenhuma vantagem criar um modelo utilizando generalização e especialização se não for para se aproveitar de um dos benefícios comentados acima.
Na verdade estaremos adicionando mais complexidade ao modelo e tornando o código menos escalável.
br>
Prática
Criei um exemplo simples em C#.NET para mostrar como aplicar os conceitos acima.
br>
Para isso no Visual Studio vá em File->New->Project.
Em Templates, escolha Console Application.
Altere o Name para Generalizacao e clique em OK

Agora vá ao projeto (Generalizacao), clique com o botão direito vá em Add->New Item.
Em Templates, escolha Class.
Altere o Nome para Habitação.

Altere o código de para que fique da seguinte forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; namespace Generalizacao { public abstract class Habitacao { /// <summary> /// Quantidade de tomadas da habitação /// </summary> private int qtdTomada; /// <summary> /// Obtem a quantidade de tomadas /// </summary> public int GetQtdTomada() { return qtdTomada; } /// <summary> /// Armazena a quantidade de tomada /// </summary> public void SetQtdTomada(int value) { qtdTomada = value; } } } |
Adiciona ao projeto as classes Casa, Predio e Galpao, e altere o código da seguinte forma:
Casa
1 2 3 4 5 6 7 8 9 10 11 | using System; namespace Generalizacao { public class Casa : Habitacao { } } |
Observação:
Em C#, a sintaxe para herança é a utilização do comando: após o nome da classe seguindo do nome da classe a ser herdada.
Em Java, a sintaxe para herança é o comando extends após nome da classe seguindo do nome da classe a ser herdada.
Predio
1 2 3 4 5 6 7 8 | using System; namespace Generalizacao { public class Predio : Habitacao { } } |
Galpao
1 2 3 4 5 6 7 8 | using System; namespace Generalizacao { public class Galpao : Habitacao { } } |
Pronto. Criamos a estrutura modelada em UML acima.
Agora nossa Solution deve ter a seguinte aparência.

Na classe Program.cs, escreva o seguinte código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | using System; namespace Generalizacao { public class Program { public static void Main(string[] args) { // Instâncias de casa Casa casa = new Casa(); casa.SetQtdTomada(15); // Instâncias de prédio Predio predio = new Predio(); predio.SetQtdTomada(300); // Instâncias de galpão Galpao galpao = new Galpao(); galpao.SetQtdTomada(40); ImprimirValorDeTomada(casa, "Casa"); ImprimirValorDeTomada(predio, "Predio"); ImprimirValorDeTomada(galpao, "Galpao"); } private static void ImprimirValorDeTomada(Habitacao habitacao,String tipo) { Console.WriteLine("{0} tem a seguinte quantidade de tomadas: {1}", tipo, habitacao.GetQtdTomada()); } } } |
Como você deve ter observado, quando estava codificando, o seguinte acontecimento. O intellisense apresentar os métodos codificados na classe Habitação, para todas as subclasses.

Isso é possível devido às classes Casa, Predio e Galpao herdarem da classe Habitação, ou seja, toda a classe que herda de Habitação terá sua característica e comportamento.
Outra coisa que podemos observar nesse exemplo é o método ImprimirValorDeTomada que recebe como parâmetro Habitação, porém é passado Casa, Predio e Galpao.
Toda subclasse pode ser convertida no tipo da superclasse. Nesse método não importa qual é o tipo de habitação e sim se é do tipo habitação.
Observação
Toda subclasse pode ser convertida no tipo da superclasse, porém para o processo inverso é necessário a realização de cast.
Exemplo:
1 2 3 4 5 | Casa casa1 = new Casa(); // conversão Implicit Habitacao hab = casa1; // conversão Explicit (Cast) Casa casa2 = (Casa)hab; |
Mas pra frente falarei mais sobre generalização.
Carlos Fernando


seguidores
leitores