Aprenda C#

  • Página Inicial
  • Contato!
  • Tudo sobre C# Parte 1!
  • Tudo sobre C# Parte 2!
  • Tudo sobre C# Parte 3!
  • Tudo sobre C# Parte 4!
  • Tudo sobre C# Parte 5!
  • Tudo sobre C# Parte 6!
  • Tudo sobre C# Parte 7!
  • Tudo sobre C# Parte 8!
  • Tudo sobre C# Parte 9!
  • Tudo sobre C# Parte 10!
  • Orientação a Objetos em C# - Parte 3

    Polimorfismo

    Basicamente, existem dois tipos de polimorfismo em C#, o de sobreposição e o de sobrecarga.

    O de sobreposição, visto anteriormente, é quando um método, indicado como virtual, é substituído em uma classe descendente, onde ele tem o mesmo nome e é indicado por override.

    E como visto nos construtores e nos campos compartilhados, podemos criar métodos comuns usando o mesmo nome, desde que os parâmetros sejam diferentes, isso é o polimorfismo de sobrecarga, como nesse exemplo:

    
    class Microondas {
        public void ligar(int minuto, int segundo) {
            if(minuto > 0 || segundo > 0) {
                Console.WriteLine("A comida estará pronta em {0}:{1:00}M.", minuto, segundo);
            }
            else {
                Console.WriteLine("Escolha um tempo maior que 0:00.");
            }
        }
    
        public void ligar(string alimento) {
            if(alimento.ToLower().Equals("pipoca")) {
                Console.WriteLine("Vamos estourar pipoca!");
            }
            else if(alimento.ToLower().Equals("bolo de caneca")) {
                Console.WriteLine("Vamos fazer bolo de caneca!");
            }
            else {
                Console.WriteLine("ERRO! Alimento desconhecido!");
            }
        }
    
        public void ligar(bool descongelar) {
            if(descongelar) {
                Console.WriteLine("Vamos descongelar o alimento!");
            }
            else {
                Console.WriteLine("ERRO! Não poderei descongelar o alimento!");
            }
        }
    
    

    Na invocação no método principal, ele será diferenciado pelo tipo de parâmetro:

    
    Microondas micro = new Microondas();
    
    micro.ligar(3, 30);
    micro.ligar("Pipoca");
    micro.ligar(true);
    
    

    Agregação de Objetos

    Vamos supor essa classe:

    
    class Pilha {
        private string marca;
        private int carga;
    
        public Pilha(string marca) {
             this.marca = marca;
             this.carga = 100;
        }
    
        public void apresentacao() {
             Console.WriteLine($"A marca da pilha é {this.marca}.");
             Console.WriteLine($"A carga da pilha é {this.carga}%.");
        }
    
        public string Marca {
            get => marca;
            set => marca = value;
        }
    
        public int Carga {
            get => carga;
            set => carga = value;
        }
    }
    
    

    Nós podemos fazer relacionamentos entre classes diferentes, veja por exemplo a classe abaixo, que tem um atributo do "tipo" da classe acima:

    
    class Aparelho {
        private Pilha pl;
    
        public Aparelho(Pilha pl) {
            this.pl = pl;
        }
    
        public void ligado() {
            if(this.pl.Carga > 0) { // Getter do objeto Pilha
                Console.WriteLine($"O aparelho está ligado e a carga da pilha é de {this.pl.Carga}%!");
            }
            else {
                Console.WriteLine($"A pilha do aparelho está sem carga!");
            }
        }
    
        public Pilha Pl {
            get => pl;
            set => pl = value;
        }
    }
    
    

    Aí podemos chamar os objetos assim:

    
    Pilha ray = new Pilha("Rayovac");
    
    ray.apresentacao();
    
    Aparelho controle = new Aparelho(ray);
    
    controle.ligado();
    
    Console.WriteLine($"A carga da pilha é de {controle.Pl.Carga}%!");
    
    

    PS: Quando a gente inicia um objeto criado dentro da classe, na verdade se chama composição. No caso acima, caso a classe Aparelho fizesse a composição de Pilha, ela teria algo como private Pilha pl = new Pilha("Rayovac"); dentro da classe Aparelho.

    Criando Tipos Genéricos

    Podemos criar também "tipos genéricos" em C#, usando apenas uma letra maiúscula, que nos permite configurar os tipos usados.

    Veja um exemplo simples de uso:

    
    class Program {
        private class Generico<E> { // Classe interna privada, com parâmetro de tipagem.
            private E entidade;
    
            public E Entidade {
                get => this.entidade;
                set => this.entidade = value;
            }
        }
    
        static void Main(string[] args) {
            Generico<string> texto = new Generico<string>();
    
            texto.Entidade = "Exemplo de String!";
    
            Console.WriteLine(texto.Entidade);
    
            Generico<int> numero = new Generico<int>();
    
            numero.Entidade = 50;
    
            Console.WriteLine(numero.Entidade);
    
            Console.Read();
        }
    }
    
    

    PS: Podemos criar normalmente uma classe externa com tipos genéricos, basta adaptar o código acima.

    Caso use mais de um tipo genérico, coloque dentro da mesma tag, separados por vírgulas. Em heranças e implementações, caso a classe a ser herdada ou a interface a ser implementada tenha tipos genéricos, a classe herdeira ou implementadora deverá ter o mesmo tipo (por exemplo, se a interface for interface NomeDaInterface<E>, a classe que a implementa deverá ter o tipo a ser recebido indicado, como por exemplo class NomeDaClasse : NomeDaInterface<Int32>, e nesse caso o objeto criado será NomeDaInterface<Int32> objeto = new NomeDaClasse(). Caso não declare o tipo genérico e queira que ele seja declarado na criação do objeto, coloque a extensão ou implementação (no caso seria class NomeDaClasse<E> : NomeDaInterface<E>), e nesse caso o objeto criado será NomeDaInterface<ClasseInvolucro> objeto = new NomeDaClasse<ClasseInvolucro>(). Esse é o conceito de polimorfismo paramétrico.