Trabalhando com classes abstratas, classes seladas e interfaces em C#
Autor: Yuri Ferreira | Publicado: 2010-08-25T13:29:00-04:00

Saudações galera!!
Bom, hoje resolvi disponibilizar para meus amigos este post do&nbsp;Rudson Kiyoshi Souza Carvalho, que explica muito bem como usar classes abstratas, classes seladas e interfaces. Na verdade, a minha idéia era tentar tirar dúvidas de amigos e até algumas minhas, espero que gostem e que através deste post possa&nbsp;esclarecer&nbsp;um pouco mais para vocês.
Trabalhando com classes abstratas, classes seladas e interfaces em C#Por Rudson Kiyoshi Souza Carvalho

Resumo

Este artigo descreve o que são Classes Abstratas, Seladas e Interfaces, e também explica quando devemos implementar cada uma delas em nosso código.

Introdução

Utilizar classes seladas é um novo conceito adicionado ao C#. O conceito de quando utilizar cada tipo de classe pode parecer um pouco confuso no início, mas após ter entendido bem os conceitos de cada uma e entender suas similaridades, poderemos partir para um desenvolvimento mais seguro e escalável, tentarei neste artigo descrever não só cada tipo de classe, mas também descrever algumas situações que devemos usar este tipo de codificação. Os exemplos de códigos abaixo utilizam a linguagem C#.

O que é uma classe abstrata? (Abstract Class)
A classe abstrata é um tipo de classe que somente pode ser herdada e não instanciada, de certa forma pode se dizer que este tipo de classe é uma classe conceitual que pode definir funcionalidades para que as suas subclasses (classes que herdam desta classe) possam implementá-las de forma não obrigatória, ou seja ao se definir um conjunto de métodos na classe abstrata não é de total obrigatoriedade a implementação de todos os métodos em suas subclasses, em uma classe abstrata os métodos declarados podem ser abstratos ou não, e suas implementações devem ser obrigatórias na subclasse ou não, quando criamos um método abstrato em uma classe abstrata sua implementação é obrigatória, caso você não implemente o mesmo o compilador criará um erro em tempo de compilação.
Exemplo de implementação retirado do books online em C#.

&nbsp;&nbsp; &nbsp;abstract class formaClasse&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; abstract public int Area();&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; class quadrado : formaClasse&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int x, y;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Se não for implementado o método Area()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // será gerado um compile-time error.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public override int Area()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x * y;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; }
O que é uma Interface? (Interface)

As interfaces são fundamentais em um sistema orientado a objetos, quando dizemos que um objeto é a instância de uma classe, na verdade queremos dizer, que este objeto implementa a interface definida pela classe, ou seja uma interface define as operações que um objeto será obrigado a implementar. Para cada operação declarada por um objeto deve ser especificado o nome da operação, os objetos que esta operação aceita como parâmetro e o tipo de valor retornado pela operação; este conjunto de informações sobre uma determinada operação tem o nome de assinatura da operação, e um conjunto de assinaturas de operações dá-se o nome de interface.

É importante lembrar que uma interface nunca contém implementação, ou seja numa interface não se pode definir campos, pois o mesmo é uma implementação de um atributo objeto, a interface também não permite construtores pois num contrutor temos as instruções usadas para inicializar campos. Para podermos usar uma interface devemos criar uma classe ou estrutura e herdar da interface, com isso é obrigatório implementar todos os métodos da interface.


Exemplo de implementação retirado do books online em C#.

&nbsp;&nbsp; &nbsp;interface IExemploInterface&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void ExemploMetodo();&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; class Implementacaoclasse : IExemploInterface&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Implementação explicita da interface&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void IExemploInterface.ExemploMetodo()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Implementação do método&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Declarando uma instancia de uma interface&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IExemploInterface obj = new Implementacaoclasse();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // chame o método.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.SampleMethod();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; }
Classes Abstratas X Interfaces

Uma classe abstrata pode conter métodos completos ou incompletos. Uma Interface pode conter apenas a assinatura de um método, mas nenhum corpo ou implementação. Portanto, em uma classe abstrata pode-se implementar métodos, mas em uma Interface não. Uma classe abstrata pode conter campos, construtores, ou destrutores e aplicar propriedades. Uma interface não pode conter campos, construtores, ou destrutores pode possuir apenas a propriedade da assinatura, mas não a implementação. Uma classe abstrata não suporta múltiplas heranças, mas uma interface pode suportar múltiplas herança. Assim, uma classe pode herdar várias interfaces, mas apenas uma classe abstrata. Uma classe que implementa uma interface tem de obrigatoriamente implementar todos os métodos da interface, mas o mesmo não é exigido no caso de uma classe abstrata. As classes abstratas são mais rápidas que as interfaces.

O que é uma classe selada? (Sealed Class)
Uma classe selada é utilizada para restringir características da herança do objeto, quando uma classe é definida como sealed, está classe não poderá ser herdada, caso você tente o compilador criara um erro em tempo de compilação, após criar uma classe selada pode se observar que o intelisense não mostra o nome da classe definida como sealed quando você tenta criar uma herança para novas classes.

Exemplo de implementação retirado do books online em C#.

&nbsp;&nbsp; &nbsp;sealed class ClasseSelada&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int x;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int y;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; class MainClass&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ClasseSelada sc = new ClasseSelada();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sc.x = 110;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sc.y = 150;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("x = {0}, y = {1}", sc.x, sc.y);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; }
Então, quando devo utilizar o que?

Classes Abstratas podem adicionar mais funcionalidades, sem destruir as funcionalidades das classes filhos que poderiam estar usando uma versão mais antiga. Classes abstratas fornecem uma maneira simples e fácil para versionar nossos componentes. Através da atualização da classe base, todas as classes que herdam são atualizadas automaticamente com a mudança. Em uma interface, a criação de funções adicionais terá um efeito sobre suas classes filhos, devido à necessidade de implementação dos Métodos criados na interface. Classes abstratas deveriam ser usadas principalmente para objetos que estão estritamente relacionados, enquanto o uso de interfaces é mais adequado para fornecer funcionalidade comum a classes independentes.
Digamos que existem duas classes, de pássaros e de aviões, e nas duas exista os métodos chamados voar(). Seria estranho para uma classe aviões herdar a partir de umas classe pássaros apenas porque necessita do método voar(). Em vez disso, o método voar() deve ser definido em uma interface e em ambas as classes pássaros e aviões devem implementar a interface. Se quisermos proporcionar uma funcionalidade em comum para os componentes, devemos utilizar uma classe abstrata.
Classes abstratas nos permitem implementar parcialmente uma classe, enquanto a interface não contem a implementação de qualquer membro. Por isso, a seleção de interface ou classes abstratas depende das necessidades e design do nosso projeto. Podemos fazer uma classe abstrata, interface, ou até uma combinação de ambas dependendo de nossas necessidades. Se desejarmos criar uma classe ou método interno para um componente ou library o ideal é utilizar o tipo sealed porque qualquer tentativa de anular algumas das suas funcionalidades não será permitida.
Nós podemos marcar uma classe ou método como selados por motivos comerciais, a fim de impedir um terceiro de modificar nossa classe. Por exemplo, no .NET a string é uma classe selada. Não devemos usar a palavra-chave sealed com um método a menos que o método seja uma mudança de outro método, ou se estamos definindo um novo método e não queremos que ninguém mais o sobreponha, não se deve declará-lo como virtual em primeiro lugar. a palavra-chave selado fornece uma maneira de garantir que ao sobrepor um método seja fornecido um "final" significa que ninguém mais poderá sobrepor-lo novamente.

Conclusão

Devemos utilizar classes abstratas quando queremos compartilhar funcionalidades em comum entre classes, e utilizar interfaces quando desejamos que uma classe possua as mesmas assinaturas porem a implementação de cada método não precise ser a mesma.

Referências

Working with Abstract classes, Sealed Classes, and Interfaces in C# by SANJIT SIL

Books online Microsoft