Quando, a nível profissional trabalhamos em certas áreas de negócio, por vezes torna-se muito complexo implementar alguns dos conceitos básicos de POO (Programação Orientada a Objectos) que aprendemos.
Nestes casos é necessário fazer um esforço extra, abstrairmo-nos dos problemas de implementação das regras de negócio, dos sistemas existentes e desenvolver uma plataforma que, além de conciliar as regras de negócio e regras de arquitectura de software, tira partido das melhores funcionalidades oferecidas pela linguagem a ser utilizada.
É certamente o caminho para uma manutenção acessível e escalável, que vai garantir a longevidade da plataforma.
Herança e Polimorfismo são alguns dos conceitos mais importantes de POO, vou falar um pouco de cada um e apresentar uma pequena demonstração.
Herança
Por vezes as próprias regras de negócio estão agrupadas em famílias, temos que aproveitar esse factor a nosso favor e desenvolver uma estrutura do mesmo tipo por forma a que a arquitectura final seja consistente.
Recorrendo à herança entre classes podemos desenvolver uma estrutura de classes agrupadas por família, e que por sua vez têm informação organizada e transversal a toda a aplicação.
Vamos olhar para um exemplo real:
public class Angariacao { public string Nome { get; set; } public string Morada { get; set; } public string EpocaBaixa { get; set; } public string EpocaAlta { get; set; } public string Enquadramento { get; set; } } public class CasaDeCampo : Angariacao { public int Capacidade { get; set; } public string Tipologia { get; set; } } public class HotelRural : Angariacao { public string Actividades { get; set; } public string Exterior { get; set; } public string AreaSocial { get; set; } }
Como podemos verificar facilmente depois de analisar o código apresentado anteriormente, existe uma lógica para agrupar todas as propriedades partilhadas pelas classes CasaDeCampo e HotelRural.
A maioria das propriedades que cada uma das classes teria, estão agora na classe Angariação e essas propriedades vão ser partilhadas nas classes CasaDeCampo e HotelRural através de herança.
Temos um grande número de vantagens ao utilizar este conceito de POO, uma delas é a fácil manutenção: caso se tenha que alterar/adicionar/remover uma propriedade na classe base, essa alteração é reflectida de forma automática em todas as classes que herdam da classe base. Torna-se também mais rápido e eficiente adicionar novas classes que herdem da classe base, pois já existem nela implementadas muitas das funcionalidades básicas bem como as propriedades partilhadas que são transversais à família de classes.
Polimorfismo e Classes Abstractas
Polimorfismo significa “tomar várias formas”, quando utilizado em POO significa que uma assinatura de um método pode ter várias implementações diferentes.
Uma classe abstracta não pode ser instanciada, apenas define as propriedades e métodos que as classes filho que vão herdar.
Para exemplificar este conceito vamos recorrer às classes apresentadas no exemplo anterior e continuar a explorar o mesmo conceito:
//A classe passou a ser abstracta public abstract class Angariacao { public string Nome { get; set; } public string Morada { get; set; } public string EpocaBaixa { get; set; } public string EpocaAlta { get; set; } public string Enquadramento { get; set; } //Definição do método a ser implementado nas //classes que herdam de Angariacao public abstract void ImprimirTipoClasse(); } public class CasaDeCampo : Angariacao { public int Capacidade { get; set; } public string Tipologia { get; set; } //Quando o método tem a assinatura abstract na classe base //é obrigatório implementar o override nas classes que herdam //da classe base public override void ImprimirTipoClasse() { Console.WriteLine(string.Format("Tipo: {0}", this.GetType())); } } public class HotelRural : Angariacao { public string Actividades { get; set; } public string Exterior { get; set; } public string AreaSocial { get; set; } //Quando o método tem a assinatura abstract na classe base //é obrigatório implementar o override nas classes que herdam //da classe base public override void ImprimirTipoClasse() { Console.WriteLine(string.Format("Tipo: {0}", this.GetType())); } }
Neste momento temos definida a família angariação, que tem como base a classe Angariação e filhos as classes CasaDeCampo e HotelRural.
A classe Angariação é abstract porque na lógica de negócio a implementar não existem objectos da classe base.
Como na classe base está declarado o método ImprimirTipoClasse com a assinatura abstract, a implementação de este método é obrigatória nas classes filho.
Para validar estes conceitos, criei um programa muito simples e que demonstra o potencial da Herança, Polimorfismo:
class Program { static void Main(string[] args) { //lista de objectos da classe base var list = new List<Angariacao>(); //adicionar à lista objectos que //herdam da classe base list.Add(new CasaDeCampo()); list.Add(new HotelRural()); foreach (var item in list) { //Imprimir no ecrã o tipo de objecto //Demonstração final de Polimorfismo item.ImprimirTipoClasse(); } Console.ReadKey(); } }
Que resulta no seguinte ecrã quando se executa a aplicação:
Para concluir, podemos verificar ao analisar a execução do programa que, embora a lista seja de objectos da classe base, podemos adicionar objectos que herdam da classe base, e quando invocamos o método ImprimirTipoClasse, o resultado é a execução do método que está definido classe filho.
Para criar um exemplo mais real, se a classe base tiver um método abstract que se chama AdicionarAngariacao, quando executado no programa da mesma forma que no exemplo acima demonstrado, iria ser adicionada uma Casa de Campo e um Hotel Rural ao sistema de acordo com as suas propriedades partilhadas e específicas, pois cada uma das classes filho implementa o método AdicionarAngariacao da forma mais conveniente.