Herança, juntamente com o encapsulamento e polimorfismo, é uma das três características primárias (ou pilares) da programação orientada a objeto. A herança permite que você crie novas classes que podem ser reutilizadas e/ou estendidas.

Classes cujos membros são herdados são chamadas de classes base, e classes que herdam esses membros são chamadas de classes derivadas. Uma classe derivada pode ter apenas uma classe base direta. No entanto, a herança é transitiva. Se ClassC é derivada da ClassB e ClassB é derivada da ClassA, ClassC herda os membros declarados em ClassB e ClassA.

Conceitualmente, uma classe derivada é uma especialização da classe base. Por exemplo, se você tem uma classe base chamada "Veiculo", você pode ter uma classe derivada chamada “Caminhao” e outra classe derivada chamada “Trator”. Um Caminhão é um veículo, assim como um Trator, mas cada classe derivada deve representar diferentes especializações da classe base. Certamente um caminhão possui características diferentes de um trator, o que resultaria em propriedades e métodos diferentes em cada classe. Da mesma maneira é certo que tanto um caminhão como um trator possuem características semelhantes, que podem ser encapsuladas na classe “Veiculo”.

Quando você define uma classe para derivar de outra classe, a classe derivada implicitamente ganha todos os membros da classe base, exceto seus construtores e destrutores. A classe derivada pode assim reutilizar o código na classe base, sem ter de voltar a implementá-lo. Na classe derivada, você pode adicionar mais membros. Desta maneira, a classe derivada estende a funcionalidade da classe base.

Podemos ver exemplos de herança nas classes do próprio .Net Framework, Por exemplo a classe CollectionBase, que contém propriedades e métodos utilizados pela maioria das classes de Collection (coleções). Ela contém propriedades como Capacity e Count e métodos como Clear() e RemoveAt().

Para utilizar a classe base em outra classe (classe derivada) você faz referência à classe base, colocando o símbolo : (dois pontos) após o nome da classe derivada e em seguida coloque o nome da classe base.

Vamos criar alguns exemplos para vermos os conceitos de herança na prática. Abaixo segue um diagrama de classes com as classes que iremos construir:



O código a seguir define uma classe base chamada AluguelItem e duas classes derivadas DVD e Livro, que herdam a classe AluguelItem.



  public class AluguelItem

        {

            string _titulo;

 

            public string Titulo

            {

                get { return _titulo; }

                set { _titulo = value; }

            }

            public Boolean VerificaEstoque(string titulo)

            {

                //codigo para verificar um item no estoque

                //returna true para demonstração

                return true;

            }

        }

        public class DVD : AluguelItem

        {

        }

        public class Livro : AluguelItem

        {

        }
As classes derivadas herdam as propriedades e métodos da classe base, sendo que as classes derivadas nada "sabem" sobre a classe base. As classes derivadas não estão limitadas às propriedades e métodos da classe base. Elas podem definir as propriedades e métodos conforme necessário. O código a seguir mostra a classe Livro definindo sua propriedade ISBN próprio.



  public class Livro : AluguelItem

        {

            string _ISBN;

 

            public string ISBN

            {

                get { return _ISBN; }

                set { _ISBN = value; }

            }

        }

Instâncias da classe Livro terão acesso tanto à propriedade "Titulo" definida na classe base AlguelItem quanto à propriedade "ISBN" definida na própria classe Livro. como demonstra a imagem abaixo:



Há muitas ocasiões em que a classe derivada precisa usar uma funcionalidade da classe base, mas também precisa adicionar alguma funcionalidade exclusiva da própria classe derivada. Neste caso, a classe derivada usa a palavras-chave base para chamar um método da classe base. Vamos exemplificar criando um método na classe DVD chamado Alugar(). Dentro dele utilizaremos o método VerificaEstoque contido na classe base, como mostrado no código a seguir.



  public class DVD : AluguelItem

        {

            public Boolean Alugar(string titulo, int idade)

            {

                if (base.VerificaEstoque(titulo))

                {

                    //Código para realizar o aluguel

                    //retorna true para demonstração

                    return true;

                }

                else

                {

                    return false;

                }

            }

        }

Métodos herdados pela classe derivada podem ser sobrecarregados assim como se faz para sobrecarregar qualquer método na mesma classe. Os nomes dos métodos devem ser os mesmos, mas as assinaturas dos métodos devem ser diferentes. O código a seguir mostra a classe Livro sobrecarregando o método VerificaEstoque da classe base AlguelItem.



  public class Livro : AluguelItem

        {

            string _ISBN;

 

            public string ISBN

            {

                get { return _ISBN; }

                set { _ISBN = value; }

            }

 

            public Boolean VerificaEstoque(string titulo, string autor)

            {

                //retorna true para demonstração

                return true;

            }

        }

Uma instância da classe Livro, terá acesso ao método original VerificaEstoque da classe base AlguelItem, bem como ao método sobrecarregado VerificaEstoque da classe Livro, como demonstra as figuras a seguir:





Neste ponto, um cliente pode criar uma instância da classe base AluguelItem como de qualquer uma das classes bases Livro ou DVD. Porém há momentos em que a classe base não é projetada para ser instanciada diretamente pelos clientes. Muitas vezes queremos que elas sejam única e exclusivamente herdadas por classes derivadas, que depois são expostas para os clientes. Estes tipos de classes base são chamados de classes abstratas. Para criar classes abstratas basta usar a palavra abstract quando vamos definir uma classe base. Exemplo:



  public abstract class AluguelItem

        {

            string _titulo;

 

            public string Titulo

            {

                get { return _titulo; }

                set { _titulo = value; }

            }

            public Boolean VerificaEstoque(string titulo)

            {

                //codigo para verificar um item no estoque

                //returna true para demonstração

                return true;

            }

        }

Dentro das Namespaces Do .Net Framework existem inúmeras classes abstratas como por exemplo, a classe TextReader, que é a classe abstrata base das classes StreamReader e StringReader por exemplo.

Neste artigo vimos os conceitos básicos de herança e como ele é usado em programação .Net Framework com C#. É importante que você entenda este conceito de forma eficiente, pois em C# basicamente tudo é orientado a objeto.

Um grande abraço a todos os leitores.