terça-feira, 16 de abril de 2013

Herança Múltipla em C#

Alguém já se pegou precisando fazer uma herança múltipla em C#? A própria ideia é bem estranha. Em tese, você herda algo genérico e extende. Porque misturar duas coisas?

Caso apareça essa necessidade, você tenha pensado bem e visto que não tem como, que você não pode transformar suas classes em interfaces, que você vai efetivamente usar os códigos separados que não pode colocar as duas classes como filhas da classe que você queria fazer herdá-las... Um milhão de aspectos a analisar. O bom seria que você pensasse muito antes de fazer.

Estou no terceiro parágrafo. Tem certeza mesmo que é isso que você quer? Ok. Vamos lá.


    public class Ornitorrinco : Pato, Castor
    {
    }

    public class Pato
    {
        public Boolean BicoMexendo { get; set; }

        public void MexeBico()
        {
            BicoMexendo = true;
        }
    }

    public class Castor
    {
        public Boolean CaldaMexendo { get; set; }

        public void MexeCalda()
        {
            CaldaMexendo = true;
        }
    }


A essa altura, o Visual Studio me diz que está esperando uma interface. É, não existe Herança Múltipla em C#. Pois é. Que triste, não? Aiai. Ok, ainda posso herdar as propriedades.


    public interface ITemBico
    {
        Boolean BicoMexendo { get; set; }
    }

    public interface ITemCalda
    {
        Boolean CaldaMexendo { get; set; }
    }

    public class Ornitorrinco : ITemBico, ITemCalda
    {
        public Boolean BicoMexendo { get; set; }
        public Boolean CaldaMexendo { get; set; }
    }

    public class Pato : ITemBico
    {
        public Boolean BicoMexendo { get; set; }

        public void MexeBico()
        {
            BicoMexendo = true;
        }
    }

    public class Castor : ITemCalda
    {
        public Boolean CaldaMexendo { get; set; }

        public void MexeCalda()
        {
            CaldaMexendo = true;
        }
    }


Uma das sugestões que vi na internet é criar um método em Ornitorrinco, inicializar um Pato / Castor dentro, e chamar o método dele. Mas como eu faço com que isso interfira nas MINHAS variáveis? Igualo o valor depois?

A ideia que tive veio de algo que adoro fazer: extender classes. Principalmente com String, ajuda bastante no entendimento do código. A parte que interessa nesse momento é que também é possível extender uma interface. O que me possibilita...

    public interface ITemBico
    {
        Boolean BicoMexendo { get; set; }
    }

    public static class TemBico
    {
        public static void MexeBico(this ITemBico temBico)
        {
            temBico.BicoMexendo = true;
        }
    }

    public interface ITemCalda
    {
        Boolean CaldaMexendo { get; set; }
    }

    public static class TemCalda
    {
        public static void MexeCalda(this ITemCalda temCalda)
        {
            temCalda.CaldaMexendo = true;
        }
    }

    public class Ornitorrinco : ITemBico, ITemCalda
    {
        public Boolean BicoMexendo { get; set; }
        public Boolean CaldaMexendo { get; set; }
    }

    public class Pato : ITemBico
    {
        public Boolean BicoMexendo { get; set; }
    }

    public class Castor : ITemCalda
    {
        public Boolean CaldaMexendo { get; set; }
    }


Agora eu posso fazer isso...

            var meuOrnitorrinco = new Ornitorrinco();
            var meuPato = new Pato();
            var meuCastor = new Castor();

            meuOrnitorrinco.MexeBico();
            meuOrnitorrinco.MexeCalda();
            meuPato.MexeBico();
            meuCastor.MexeCalda();

...sabendo que o código não está repetido e correndo risco de uma correção ou um refactor afetar uma coisa e não outra. É, eu sei, o último código ficou parecendo música da Xuxa.

Sim, é possível. Raramente será a solução correta. As propriedades usadas pelos métodos terão que ficar expostas. Se for fazer, tenha certeza de não usar o mesmo nome de método para duas interfaces que serão herdadas pela mesma classe.

Meu exemplo não é um Ornitorrinco a toa...

Nenhum comentário:

Postar um comentário