Article Details                  
 
Novidades C# 2.0 - parte III (Tipos parciais)

Introduz os principais conceitos relativos à utilização de tipos parciais.

Novidades C# 2.0 - parte III (Tipos parciais)


Autor: Luís Abreu

Conteúdo: Novidades existentes na nova framework 2.0 (
Tipos parciais)

Ferramentas: Visual C# Express


A versão 1.X da framework obriga a que a definição de um tipo esteja contida num único ficheiro. Apesar deste principio poder ser considerado como sendo boa prática de programação, também pode introduzir alguns problemas. Se tivermos em atenção que hoje praticamente toda a gente escreve código a partir de geradores de código e utiliza wizards et at para adicionar features às aplicações, então podemos concluir que provavelmente teríamos algo a ganhar se fosse possível dividir o código em pelo menos dois ficheiros de forma a que um deles fosse actualizado pelos geradores/wizards e o outro contivesse o "nosso próprio código".


Na nova versão da framework a Microsoft teve estas questões em conta e optou por introduzir uma nova feature que permite definir um tipo em ficheiros separados. Para tal temos de utilizar os chamados tipos parciais (ou, se preferirem, partial types).


Introdução aos tipos parciais


A definição de um tipo parcial é feita através do termo partial. Convém referir que este termo só tem um significado especial se preceder os termos reservados class, struct e interface. O termo deverá ser aplicado nas várias partes que consituem a classe, ou seja, se tivermos uma classe espalhada por dois ficheiros, então deveremos aplicar o termo nos dois ficheiros. O exemplo seguinte apresenta uma classe bastante simples que recorre a esta nova feature pois está dividida em dois ficheiros


 
//ficheiro 1
public partial class Test
{
public Test( )
{
_t = 29;
}
public void PrintInfo()
{
Console.WriteLine( _t.ToString( ) );
}
}

//ficheiro2
public partial class Test
{
private int _t;
}


Convém referrir que esta é a estratégia utilizada pelo Visual Studio (pelo menos a nível das express tools - a única versão de que disponho) para criar novos formulários num projecto (windows forms e asp.net). Portanto, a utilização do termo partial assume um significado especial quando precede o termo class, struct ou interface. Este termo indica ao compilador que a definição da classe pode estar separada em vários ficheiros. O fundamental aqui é salientar que o termo partial apenas dá a indicação de que poderá haver mais informação relativa à classe noutro local; não é obrigatório que tal aconteça (ou seja, podemos aplicar o termo partial a uma classe sem que essa classe não esteja contida em vários ficheiros).


Atributos e modificadores


Os atributos aplicados a uma classe resultam da junção de todos os atributos aplicados ás definições espalhadas pelos vários ficheiros. É importante ter em atenção que não existe nada que indique uma ordem pela qual os atributos serão aplicados. Por outro lado, se um mesmo atributo for aplicado em ficheiros diferentes, então é como se aplicássemos o mesmo atributo várias vezes à classe.


Quando uma classe está espalhada por vários ficheiros, todas as definições têm de estar de acordo quanto ao modificador, ou seja, se num ficheiro definirmos uma classe como sendo pública (public) todas as outras classes parciais têm de possuir o mesmo tipo de acesso. Contudo, é possível definirmos o tipo de acesso apenas numa das classes parciais. O que não pode acontecer é definirmos um acesso num local e outro noutro, pois o compilador irá gerar um erro se tal acontecer.


Se uma das definições das classes parciais contiver o modificador abstract, então a classe será considerada abstracta (abstract). Se uma das classes for anotada com o modificador sealed, então a classe será automaticamente considerada como fechada (sealed). ah, é verdade...como todos sabem, uma classe não pode ser simultaneamente abstracta e fechada.


Classes base, interfaces e genéricos


Quando uma classe parcial inclui uma herança explicita, então todas as classes têm de especificar o mesmo tipo de herança. Portanto, não é possível termos uma classe parcial a herdar da classe A num ficheiro e da classe B noutro ficheiro. No caso dos interfaces, é possível definirmos vários interfaces num mesmo ficheiro ou em ficheiros diferentes. Por exemplo:



partial class Test: IA { ... }
partial class Test: IB { ... }

No exemplo anterior a classe Test implementa os interfaces IA e IB. O que nunca pode acontecer é implementarmos os membros dos interfaces de forma repetida em ficheiros diferentes. Geralmente, e seguindo uma certa lógica, a implementação de um interface costuma estar colocada no ficheiro em que é especificada a herança do interface. Contudo, não há nada que obrigue a que isso aconteça.


Se quisermos, podemos também aplicar os tipos parciais à construção de uma classe genérica. Neste caso é obrigatório que todas as definições da classe (que se encontram espalhadas por vários ficheiros) definam explicitamente os mesmos parâmetros genéricos. Se uma definição parcial contiver uma lista de restrições, então as restantes definições das classes parciais têm de ter as mesmas restrições (isto se decidirem apresentar uma lista de restrições). O exemplo seguinte demonstra estes principios:



partial Test
where T:IMyInterface
where T:IMyInterface2

partial Test { ... } //ok: nao especifica lista de restricoes


Como o exemplo anterior demonstra, não é obrigatório explicitar a lista de restrições em todos os locais onde a classe é definida; o que é obrigatório é, a partir da altura em que definimos uma restrição, então temos de escrever todas as restrições de forma a que todas as classes parciais possuam as mesmas restrições (no exemplo anterior, se na segunda definição colocássemos uma das restrições então teríamos obrigatoriamente de colocar ambas!).


Outros aspectos


Não há muito mais a dizer em relação a esta nova feature. Para terminar, vamos apenas adicionar mais algumas questões:



  • os membros de um tipo resultam da união dos diferentes membros definidos nos vários ficheiros;

  • não é possível definir o mesmo membro duas vezes em ficheiros separados;


Conclusões finais


Ao longo deste artigo foram apresentadas as regras relativas à utilização de tipos parciais. Apesar dos (poucos) exemplos terem recorrido a classes, também é possível definir outros tipos parciais: estruturas (structs) e interfaces. No próximo item desta série (que também será o último) iremos falar acerca de iterators.


Por favor enviem-me as vossas opiniões/sugestões/críticas/correcções para progC@netmadeira.com.


Fiquem bem e boa programação! Até à próxima.


Leiam o meu blog em: http://weblogs.pontonetpt.com/luisabreu


Written By: labreu
Date Posted: 4/14/2006
Number of Views: 368

Return