domingo, 28 de junho de 2009

C# - Classe selada (sealed class)

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2009/06/28/C-Classe-selada-(sealed-class).aspx


Todo método declarado como sealed não pode ser reescrito em classes derivadas. Por consequência, toda classe declarada como sealed não pode ser classe base de outras classes.

C# - Classes abstratas

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2009/06/28/C-Classes-abstratas.aspx


Uma classe abstrata é utilizada quando deseja-se fornecer uma interface comum a diversos membros de uma hierarquia de classes. Os métodos declarados na classe abstrata serão implementados em suas subclasses, através de polimorfismo.

É importante salientar que uma classe abstrata não pode ser instanciada. Uma classe que contenha métodos abstratos deve ser declarada como abstract mesmo que contenha métodos concretos.

Abaixo, temos um exemplo de classe abstrata com um método abstrato. Na linha 44 é definido o método abstrato. Esse método deverá ser implementado nas classes derivadas da classe Empregado.

   1:  abstract class Empregado

   2:  {

   3:      private string primeiroNome;

   4:      private string ultimoNome;

   5:      private string numeroSeguroSocial;

   6:   

   7:      public Empregado(string primeiro, string ultimo, string nss)

   8:      {

   9:          primeiroNome = primeiro;

  10:          ultimoNome = ultimo;

  11:          numeroSeguroSocial = nss;

  12:      }

  13:   

  14:      public string PrimeiroNome

  15:      {

  16:          get

  17:          {

  18:              return primeiroNome;

  19:          }

  20:      }

  21:   

  22:      public string UltimoNome

  23:      {

  24:          get

  25:          {

  26:              return ultimoNome;

  27:          }

  28:      }

  29:   

  30:      public string NumeroSeguroSocial

  31:      {

  32:          get

  33:          {

  34:              return numeroSeguroSocial;

  35:          }

  36:      }

  37:   

  38:      public override string ToString()

  39:      {

  40:          return string.Format("{0} {1}\nNúmero do Seguro Social: {3}", PrimeiroNome, UltimoNome, NumeroSeguroSocial);

  41:      }

  42:   

  43:      // método abstrato que será implementado pela classe derivada

  44:      public abstract decimal Salario();

  45:  }



Vamos utilizar como exemplo um sistema de folha de pagamento (exemplo do livro do Deitel) para implementar a classe Empregado utilizando polimorfismo. O código para implementação de uma classe abstrata é o mesmo da herança: ClasseAbstrata : ClasseDerivada.

Abaixo, o diagrama de classes do sistema de folha de pagamento (sem os métodos e atributos):



O código abaixo é da classe derivada EmpregadoAssalariado. Na linha 1 está o código que informa que a classe EmpregadoAssalariado implementa a classe Empregado.


   1:  class EmpregadoAssalariado : Empregado

   2:  {

   3:      private decimal salarioSemanal;

   4:   

   5:      public EmpregadoAssalariado(string primeiro, string ultimo, string nss, decimal salario)

   6:          : base(primeiro, ultimo, nss)

   7:      {

   8:          SalarioSemanal = salario;

   9:      }

  10:   

  11:      public decimal SalarioSemanal

  12:      {

  13:          get

  14:          {

  15:              return salarioSemanal;

  16:          }

  17:   

  18:          set

  19:          {

  20:              salarioSemanal = (value >= 0) ? value : 0;

  21:          }

  22:      }

  23:   

  24:      public override decimal Salario()

  25:      {

  26:          return SalarioSemanal;

  27:      }

  28:   

  29:      public override string ToString()

  30:      {

  31:          return string.Format( "Empregado assalariado: {0}\n{1}: {2:C}", base.ToString(), "salário semanal", SalarioSemanal);

  32:      }

  33:  }


Agora, a implementação da classe EmpregadoPagoPorHora

   1:  class EmpregadoPagoPorHora : Empregado

   2:  {

   3:      private decimal salarioPorHora;

   4:      private decimal horas;

   5:   

   6:      public EmpregadoPagoPorHora(string primeiro, string ultimo, string nss, decimal salarioPorHora, decimal horasTrabalhadas)

   7:          : base(primeiro, ultimo, nss)

   8:      {

   9:          SalarioPorHora = salarioPorHora;

  10:          Horas = horasTrabalhadas;

  11:      }

  12:   

  13:      public decimal SalarioPorHora

  14:      {

  15:          get

  16:          {

  17:              return salarioPorHora;

  18:          }

  19:   

  20:          set

  21:          {

  22:              salarioPorHora = (value >= 0) ? value : 0;

  23:          }

  24:      }

  25:   

  26:      public decimal Horas

  27:      {

  28:          get

  29:          {

  30:              return horas;

  31:          }

  32:   

  33:          set

  34:          {

  35:              horas = (value >= 0) ? value : 0;

  36:          }

  37:      }

  38:   

  39:      public override decimal Salario()

  40:      {

  41:          if (Horas <= 40) //sem horas extras

  42:              return SalarioPorHora * Horas;

  43:          else

  44:              return (40 * SalarioPorHora) + ((Horas - 40) * SalarioPorHora * 1.5M);

  45:      }

  46:   

  47:      public override string ToString()

  48:      {

  49:          return string.Format("empregado pago por hora: {0}\n{1}: {2:C}; {3}: {4:F2}", base.ToString(), "salário por hora", SalarioPorHora, "horas trabalhadas", Horas);

  50:      }

  51:  }



Em seguida, a implementação da classe EmpregadoComissionado:

   1:  class EmpregadoComissionado : Empregado

   2:  {

   3:      private decimal vendaBruta;

   4:      private decimal taxaDeComissao;

   5:   

   6:      public EmpregadoComissionado(string primeiro, string ultimo, string nss, decimal vendas, decimal taxa)

   7:          : base(primeiro, ultimo, nss)

   8:      {

   9:          VendaBruta = vendas;

  10:          TaxaDeComissao = taxa;

  11:      }

  12:   

  13:      public decimal TaxaDeComissao

  14:      {

  15:          get

  16:          {

  17:              return taxaDeComissao;

  18:          }

  19:   

  20:          set

  21:          {

  22:              taxaDeComissao = (value > 0 && value < 1) ? value : 0;

  23:          }

  24:      }

  25:   

  26:      public decimal VendaBruta

  27:      {

  28:          get

  29:          {

  30:              return vendaBruta;

  31:          }

  32:   

  33:          set

  34:          {

  35:              vendaBruta = (value >= 0) ? value : 0;

  36:          }

  37:      }

  38:   

  39:      public override decimal Salario()

  40:      {

  41:          return TaxaDeComissao * VendaBruta;

  42:      }

  43:   

  44:      public override string ToString()

  45:      {

  46:          return string.Format( "{0}: {1}\n{2}: {3:C}\n{4}: {5:F2}", "empregado comissionado", base.ToString(), "venda bruta", VendaBruta, "taxa de comissão", TaxaDeComissao);

  47:      }

  48:  }



A classe EmpregadoComissionadoMaisSalarioBase é uma classe derivada da classe EmpregadoComissionado e, por consequência, também implementa o método abstrato da classe Empregado.

   1:  class EmpregadoComissionadoMaisSalarioBase : EmpregadoComissionado

   2:  {

   3:      private decimal salarioBase;

   4:   

   5:      public EmpregadoComissionadoMaisSalarioBase(string primeiro, string ultimo, string nss, decimal vendas, decimal taxa, decimal salario)

   6:          : base(primeiro, ultimo, nss, vendas, taxa)

   7:      {

   8:          SalarioBase = salario;

   9:      }

  10:   

  11:      public decimal SalarioBase

  12:      {

  13:          get

  14:          {

  15:              return salarioBase;

  16:          }

  17:   

  18:          set

  19:          {

  20:              salarioBase = (value >= 0) ? value : 0;

  21:          }

  22:      }

  23:   

  24:      public override decimal Salario()

  25:      {

  26:          return base.Salario();

  27:      }

  28:   

  29:      public override string ToString()

  30:      {

  31:          return string.Format( "{0} {1}; {2}: {3:C}", "com salário base", base.ToString(), "salário base", SalarioBase);

  32:      }

  33:  }



Agora chegou a hora de implementar esse código para entender como ele irá funcionar.

   1:  class Program

   2:  {

   3:      static void Main(string[] args)

   4:      {

   5:          EmpregadoAssalariado empregadoAssalariado = new EmpregadoAssalariado("John", "Smith", "111-11-1111", 800.00M);

   6:          EmpregadoPagoPorHora empregadoPagoPorHora = new EmpregadoPagoPorHora("Karen", "Price", "222-22-2222", 16.75M, 40.0M);

   7:          EmpregadoComissionado empregadoComissionado = new EmpregadoComissionado("Sue", "Jones", "333-33-3333", 10000.00M, .06M);

   8:          EmpregadoComissionadoMaisSalarioBase empregadoComissionadoMaisSalarioBase = new EmpregadoComissionadoMaisSalarioBase("Bob", "Lewis", "444-44-4444", 5000.00M, .04M, 300.00M);

   9:   

  10:          Console.WriteLine("Empregados processados individualmente:\n");

  11:          Console.WriteLine("{0}\n{1}: {2:C}\n", empregadoAssalariado, "earned", empregadoAssalariado.Salario());

  12:          Console.WriteLine("{0}\n{1}: {2:C}\n", empregadoPagoPorHora, "earned", empregadoPagoPorHora.Salario());

  13:          Console.WriteLine("{0}\n{1}: {2:C}\n", empregadoComissionado, "earned", empregadoComissionado.Salario());

  14:          Console.WriteLine("{0}\n{1}: {2:C}\n", empregadoComissionadoMaisSalarioBase, "earned", empregadoComissionadoMaisSalarioBase.Salario());

  15:   

  16:          Empregado[] empregados = new Empregado[4];

  17:          empregados[0] = empregadoAssalariado;

  18:          empregados[1] = empregadoPagoPorHora;

  19:          empregados[2] = empregadoComissionado;

  20:          empregados[3] = empregadoComissionadoMaisSalarioBase;

  21:   

  22:          Console.WriteLine("Empregados processados polimorficamente:\n");

  23:   

  24:          foreach (Empregado empregadoAtual in empregados)

  25:          {

  26:              Console.WriteLine(empregadoAtual);

  27:   

  28:              if (empregadoAtual is EmpregadoComissionadoMaisSalarioBase)

  29:              {

  30:                  EmpregadoComissionadoMaisSalarioBase empregado = (EmpregadoComissionadoMaisSalarioBase)empregadoAtual;

  31:                  empregado.SalarioBase *= 1.10M;

  32:                  Console.WriteLine("Novo salário base com 10% de aumento: " + empregado.SalarioBase.ToString());

  33:              }

  34:   

  35:              Console.WriteLine("salário ganho: " + empregadoAtual.Salario() + "\n");

  36:          }

  37:   

  38:          for (int i = 0; i < empregados.Length; i++)

  39:              Console.WriteLine("Empregado " + i.ToString() + " é um " + empregados[i].GetType());

  40:   

  41:          Console.ReadLine();

  42:      }

  43:  }