Arquivos da categoria: Orientação a Objetos

Coleções em C# usando List

csharplogo

Nas linguagens de programação, o termo coleção é utilizado para definir estruturas capazes de agrupar objetos. Um simples vetor/array pode ser definido como uma coleção, neste caso, estática.

Em C# é facilmente possível criar coleções dinâmicas com o classe List<T>, disponível no namespace System.Collections.Generic.

Uma coleção gerada com List<T> fornece uma ótima opção, quando precisamos agrupar tipos de objetos (por exemplo, classes) de forma dinâmica e eficiente, e com métodos que possibilitam filtrar, ordenar e seus itens.

Vamos aos exemplos:

1 – Criando uma classe.

public class Pessoa
{
    int _id;

    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }
    string _nome;

    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }

    public Pessoa()
    {
        _id = 0;
        _nome = &quot;&quot;;
    }

    public Pessoa(int id, string nome)
    {
        this._id = id;
        this._nome = nome;
    }
}

2 – Criando e manipulando uma coleção da classe Pessoa (deve referenciar o namespace System.Collections.Generic).

using System.Collections.Generic;

//Criando uma lista que agrupará objetos da classe Pessoa.
List&lt;Pessoa&gt; pessoas = new List&lt;Pessoa&gt;();

//Adicionando objetos (tipo Pessoa) na lista.
pessoas.Add(new Pessoa(1, &quot;Andre&quot;));
pessoas.Add(new Pessoa(2, &quot;Brenda&quot;));

//Percorrendo a lista.
foreach (Pessoa p in pessoas)
{
   Console.WriteLine(p.Nome);
}

//Localizando uma pessoa.
Pessoa pessoa = pessoas.Find(delegate(Pessoa p1) { return p1.Id == 2; });

//Localizando várias pessoas que contenham no nome as letras &quot;nd&quot; (neste caso, o retorno é uma outra List&lt;Pessoas&gt; com as pessoas localizadas).
List&lt;Pessoa&gt; pessoasLocalizadas = pessoas.FindAll(delegate(Pessoa p1) { return p1.Nome.Contains(&quot;nd&quot;); });


//Removendo um item da lista pela sua posição.
pessoas.RemoveAt(0);

Mais detalhes em http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx.

Até…

Definindo classes em C# – Parte 5

Passagem de parâmetros: Os modificadores in/out/ref

Ao criamos parâmetros em métodos na linguagem C#, por padrão estes parâmetros são passados por valor, ou seja, se os valores dos parâmetros forem alterados durante a execução do método, a mudança não será refletida na variável passada por parâmetro. Este comportamento é atribuído ao modificador de parâmetro in, e é implícito, não precisa ser informado.

public void Metodo1(int p1)
{
     p1 = 1000;
}

No exemplo acima, mesmo que o parâmetro p1 fosse alterado dentro do método seu valor externamente não seria modificado. Este comportamento pode ser alterado utilizado os moficadores ref e out.

O modificador ref

O parâmetro ref permite a passagem de valores por referência. Neste caso, os valores modificados dentro do método refletem para o bloco de código que fez a chamada. Na utilização, o operador ref é necessário tanto na declaração do parâmetro como também na chamada do método. E ainda o uso do ref requer que a variável a ser passada como parâmetro seja inicializada antes de passar sua referência. No exemplo abaixo, a variável valor é inicializada com o valor 1000, e depois é enviado por referência ao método.

double valor = 1000.00;
Metodo2(ref valor);

...

public void Metodo2(ref double p1)
{
     p1 = 0;
}

O modificador out

A diferença entre o modificador out e o ref, é que o out permite a passagem de uma variável não inicializada por parâmetro, o que não é permitido em parâmetros do tipo ref.

double valor;
Metodo3(out valor);

...

public void Metodo3(out double p1)
{
     p1 = 1000;
     ...
     ...
}

Outra difrença no uso do modificador out, é que o parâmetro obrigatoriamente deve ter um valor atribuído dentro do método, antes de deixá-lo. No exemplo acima, o parâmetro p1 recebe o valor 1000.

Um método naturalmente só pode retornar um valor através da palavra reservada return. Um prática comum é usar parâmetros out para retornar vários.

Definindo classes em C# – Parte 4

Herança

Herança é um tipo de relacionamento/associação entre classes. É usada quando é necessário que uma determinada classe tenha todas as características de outra classe com algumas modificações em seu comportamento, ou mesmo algumas funcionalidades adicionais.

As palavras generelização e especialização fazem parte do conceito de Herança. Uma classe “mais genérica” (generelização) pode gerar uma nova classe que herda suas características, mas permitindo modificações e novas implementações, ou seja, a nova classe é uma especialização da classe genérica.

Um exemplo tradicional usado para explicar o conceito de herança é a definição das classes Pessoa, PessoaFisica e PessoaJuridica. A classe Pessoa é genérica, e contém atributos, métodos e propriedades que podem representar qualquer pessoa. Já as classes PessoaFisica e PessoaJuridica respectivamente representam uma características para uma pessoa física e pessoa jurídica, e são classes especializadas, pois especializam a classe Pessoa.

Em C# uma relação de Herança é implementada com o uso do símbolo “:” (dois pontos) na definição da classe.

Classe genérica (Pessoa).

public class Pessoa
{
    int _id;
    DateTime _dataCadastro;

    public int Id
    {
        get { return this._id; }
        set { this._id = value; }
    }

    public DateTime DataCadastro
    {
        get { return _dataCadastro; }
        set { _dataCadastro = value; }
    }

    public int GerarId()
    {
        throw new NotImplementedException();
    }
}

Classes especializadas PessoaFisica e PessoaJuridica.

public class PessoaFisica: Pessoa
{
    string _nome;
    DateTime _dataNascimento;
    string _cpf;

    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }

    public DateTime DataNascimento
    {
        get { return _dataNascimento; }
        set { _dataNascimento = value; }
    }

    public PessoaFisica(int id, DateTime dataCadastro, string nome, string cpf)
    {
        base.Id = id;
        base.DataCadastro = dataCadastro;
        this._cpf = cpf;
        this._nome = nome;
    }

    public PessoaFisica EncontrarPorCpf(string cpf)
    {
        throw new NotImplementedException();
    }
}

public class PessoaJuridica : Pessoa
{
    string _cnpj;
    string _razaoSocial;

    public string Cnpj
    {
        get { return _cnpj; }
        set { _cnpj = value; }
    }

    public string RazaoSocial
    {
        get { return _razaoSocial; }
        set { _razaoSocial = value; }
    }

    public PessoaJuridica(int id, DateTime dataCadastro, string cnpj, string razaoSocial)
    {
        base.Id = id;
        base.DataCadastro = dataCadastro;
        this._cnpj = cnpj;
        this._razaoSocial = razaoSocial;
    }

    public PessoaJuridica EncontrarPorCnpj(string cnpj)
    {
        throw new NotImplementedException();
    }
}

Graficamente a Herança no Diagrama de Classe tem o seguinte aspecto.

Como é possível perceber no exemplo acima, as classes especializadas tem acesso aos membros implementados na classe genérica atráves da palavra reservada base.

Métodos Virtuais

A classe genérica pode oferecer métodos que podem ser reescritos nas classes especializadas. Isso é possível quando um método é decorado com a palavra reservada virtual. Para reescrevê-lo na classe especializada, o método deve ser decorado com a palavra reservada override.

public class Pessoa
{
    ...

    public virtual Pessoa EncontarPorId(int id)
    {
        throw new NotImplementedException();
    }
}

public class PessoaJuridica : Pessoa
{
    ...

    public override Pessoa EncontarPorId(int id)
    {
        //Nova implementação
    }
}

public class PessoaFisica : Pessoa
{
    ...

    public override Pessoa EncontarPorId(int id)
    {
        //Nova implementação
    }
}

Por enquanto é só isso. Até o próximo.

Definindo classes em C# – Parte 3

Sobrecarga de Métodos (overloading)

A linguagem C# permite que métodos diferentes possuam o mesmo nome. Essa implementação é possível pois a assinatura dos métodos são diferentes. Uma assinatura é formada pelo nome do método e sua lista de parâmetros.

Geralmente o uso da sobrecarga está associada quando uma método precisa de uma série de métodos que adotem parâmetros diferentes, mas que fazem conceitualmente a mesma coisa, como por exemplo quando necessitamos ter parâmetros opcionais, diferentes tipos de entrada ou diferentes tipos de saídas (através dos parâmetros).

public void FaçoAlgumaCoisa()
{
}

public void FaçoAlgumaCoisa(int p1)
{
}

public void FaçoAlgumaCoisa(int p1, int p2)
{
}

public void FaçoAlgumaCoisa(string p1, int p2)
{
}

public void FaçoAlgumaCoisa(int p1, int p2, out int p3)
{
}

A invocação dos metódos acontece de forma tradicional. O compilador da linguagem chamará o método correto conforme a lista dos parâmetos.

FaçoAlgumaCoisa();
FaçoAlgumaCoisa(1);
FaçoAlgumaCoisa(1, 2);
FaçoAlgumaCoisa(&quot;1&quot;, 2);

int x;
FaçoAlgumaCoisa(1,2, out x);

Quando usamos o VisualStudio o autocomplete dá um força mostrando as sobrecargas do método.

Até mais.

Definindo classes em C# – Parte 2

Métodos Estáticos

No post anterior vimos que uma classe pode ser instanciada, e que cada instância é chamada de objeto. Cada objeto é independente, ou seja, instâncias da mesma classe “não se conhecem”, não compartilham dados.

Pessoa pessoa1 = new Pessoa();
Pessoa pessoa2 = new Pessoa(1,&quot;Filogonio Silva&quot;,dataNasc);
Pessoa pessoa3 = new Pessoa(2,&quot;Fippildo Silva&quot;,dataNasc);

No código acima, as instâncias (ou objetos) da classe Pessoa, pessoa1, pessoa2 e pessoa3 contêm seus próprios dados. Os membros criados na classe somente podem ser vistos por seus respectivos objetos, pois foram definidos como membros de objetos. Há caso que esse não é o comportamento desejado. É possível definir membros da classe, que são chamados de membros estáticos, não sendo necessário instanciar a classe para usá-los.

A declaração de um membro estático se dá através da palavra reservada static. Um membro estático está disponível desde o momento que o programa é executado.

O código abaixo exemplifica a definição de um atributo estático e sua respectiva propriedade (somente get) para retorna seu valor.

//atributo estático
static int _tamanhoNome = 100;

//propriedade estática
public static int TamanhoNome
{
    get { return _tamanhoNome; }
}

Como dito anteriormente, um membro estático existe deste a execução do programa, não sendo necessária a instanciação da classe, basta acessar a classe e invocar o membro estático.

Pessoa pessoa1 = new Pessoa();
Pessoa pessoa2 = new Pessoa(1, &quot;Filogonio Silva&quot;, dataNasc);
Pessoa pessoa3 = new Pessoa(2, &quot;Fippildo Silva&quot;, dataNasc);

//Uso de propriedade estática.
Response.Write(Pessoa.TamanhoNome);

Para finalizar, é importante destacar que um método estático não pode acessar outros membros da classe que não sejam estáticos.

Até o próximo…

Definindo classes em C# – Parte 1

Olá pessoal.

A ideia deste post não é mostrar o conceito de classe (ou mesmo da Orientação a Objetos), e sim como criar classes na linguagem C#.

Numa aplicação desenvolvida com uma linguagem orientada a objetos o uso de classe é bem comum. Mesmo aplicações pequenas em C# necessitam da elaboração de uma ou mais classes, cada uma com suas propriedades e métodos usados para executar as tarefas relativas ao objeto.

Mas o que é uma classe? Uma classe pode ser definida como um gabarito de um objeto. Acho que agora piorou, certo?

Primeiro vamos entender o que é um objeto. Um objeto na programação OO é qualquer coisa que seja um único item que se queira identificar num programa, como por exemplo uma pessoa, um carro, um computador, uma caneta, um usuário, etc. Mas o que seria a classe? A classe define como esse objeto deve ser, por isso é um gabarito de um objeto.

A classe gera o objeto de acordo com sua estrutura, e esse processo de criação do objeto é chamado de instanciação da classe.

Em C#, podemos ter dentro de uma classe os seguintes membros: atributos, construtores, destrutores, domínios, métodos, propriedades, indexadores, delegates, eventos e classe aninhadas. As classes são declaradas usando a palavra reservada class e precedida de um modificador de acesso, conforme mostrado no exemplo a seguir

public class Pessoa
{
}

Os modificadores de acesso dizem ao compilador da linguagem como classe será acessada externamente. Os moficadores são para classe são:

public: Permite que a classe seja acessada por qualquer outra classe.
selead: Não permite que a classe seja herdada.
partial: Permite que a classe tenha seu escopo dividido em vários arquivos.
static: Especifica que a classe somente tem membros estáticos. Não pode ser instanciada.
abstract: Define moldes para classes filhas. Não pode ser instanciada.

Atributos, Métodos, Propriedades e Construtores

Atributos

Atributo são declarados dentro da classe e são os elementos que definem sua estrutura. São como variáveis da classe.

public class Pessoa
{
    int _id;
    string _nome;
    DateTime _dataNascimento;
}

Métodos

Os métodos são as ações que a classe ou uma instância da classe realização. A declaração de um método contempla um modificador de acesso, um tipo de retorno, o nome do método e opcionalmente parâmetros.

public class Pessoa
{
    int _id;
    string _nome;
    DateTime _dataNascimento;

    public int CalcularIdade()
    {
        int idade = DateTime.Now.Year - this._dataNascimento.Year;
        return (idade);
    }

    public int CalcularIdade(DateTime dataReferencia)
    {
        int idade = dataReferencia.Year - this._dataNascimento.Year;
        return (idade);
    }
}

É possível ter métodos com o mesmos nomes, sendo suas assinaturas diferentes, isso é chamado de sobrecarga de métodos. E ainda é possível criar métodos que não tenham um retorno específico usando a palavra reservada void.

protected void FazAlgumaCoisa()
{
    //Faz alguma coisa e não retorna...
}

Um método é classificado em “Contexto de Ação”, quando é centrado nos processos e atividades realizadas. Ex.: impressão de um cabeçalho padrão, mudança de configuração de tela, mudança de um status, etc. Normalmente não possuem retorno. É classificado como “Contexto de Resultado”, quando o objetivo é calcular ou obter algum valor em especial. Ex.: validação, resultado de um cálculo, etc. Normalmente retorna um valor.

Propriedades

Algumas linguagens de programação implementam o conceito Propriedades em suas características de Orientação a Objetos. Alguns puristas não concordam com uso, pois alegam que fere alguns conceitos tradicionais da OO.

A linguagem C# promove o uso de Propriedades, que são métodos que protegem (encapsulam) o acesso a membros da classe, ou seja, separa os elementos visíveis de um objeto dos invisíveis. As propriedades podem ser substituidas pelo clássico uso dos métodos set e get.

public class Pessoa
{
    int _id;

    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }

    string _nome;

    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }

    DateTime _dataNascimento;

    public DateTime DataNascimento
    {
        get { return _dataNascimento; }
        set { _dataNascimento = value; }
    }
}

Na classe acima todos atributos foram encapsulados por propriedades, por exemplo o atributo int _id foi encapsulado pela propriedade public int Id. A propriedade Id poderia ter sido substituída sem problemas por um método set e get.

int _id;

public int GetId
{
    return _id;
}

public int SetId
{
    _id = value;
}

Modificações de acesso para atributos, métodos e propriedades

Atributos, métodos e propriedades necessitam de moficadores de acesso. Os principais para estes recursos são:

Public: Permite que os membros das classes sejam acessados por qualquer outro escopo
Protected: Permite que membros sejam usados apenas pela classe que o contém e permite que estes sejam “herdados” para classes derivadas da original.
Private: O membro é de uso exclusivo da classe onde é declarado.
Internal: Permite acesso somente por classes do mesmo assemblie.
Static: Permite acesso, sem necessidade do objeto ser instanciado.
Abstract: São métodos de classes Abstract que não possuem implementação (sem codificação).
Virtual: Permite que os métodos sejam sobrescritos por classes filhas.
Readonly:Limita acesso a somente leitura aos atributos da classe

Construtores

As classes podem apresentar métodos de inicialização chamados de construtores. São métodos responsáveis por inicializar os objetos das classes (instâncias das classes). E são identificados por um método com o mesmo nome da classe e sem retorno.

public class Pessoa
{
    public Pessoa()
    {

    }

    public Pessoa(int id, string nome, DateTime dataNascimento)
    {
        _id = id;
        _nome = nome;
        _dataNascimento = dataNascimento;

    }
    ...

Acima foram criados dois construtores, o primeiro não faz nada (construtor padrão) e o segundo recebendo valores para inicializar os atributos da classe.

Instanciando classes

A instanciação da classe ocorre através da palavra reservada new. Se uma classe é estática (static) ela tem um comportamente diferente, não sendo necessário fazer sua instanciação para uso.

Pessoa pessoa1 = new Pessoa();
Pessoa pessoa2 = new Pessoa(1,&quot;Filogonio Silva&quot;,dataNasc);
Pessoa pessoa3 = new Pessoa(2,&quot;Fippildo Silva&quot;,dataNasc);

Existe outros conceitos (mais avançados) envolvendo classes. Aqui é só um “aquece”.

Até mais.

Parâmetros opcionais em C# (versão 4)

Imagine a necessidade de ter parâmetros com valor padrão. Isso é possível utilizando os parâmetros nomeados na linguagem C# versão 4.
Os parâmetros opcionais devem ser os últimos parâmetros da lista além de terem uma valor padrão. O valor padrão será usado pelo método quando o valor do parâmentro não for fornecido.

Vamos aos exemplos.

O método SomarA é um método tradicional, sendo necessário passar dois valores, x e y. O método SomarB é um método que só tem um parâmetro tradicional, x. O parâmetro y e z são opcionais. Se o valor de y ou z não forem informados na chamada ao método, seu valor padrão será utilizado (y=100, z = 200).

protected void Page_Load(object sender, EventArgs e)
 {
        int v1 = SomarA(1, 2);
        int v2 = SomarB(1);
        int v3 = SomarB(1, y: 2);
        int v4 = SomarB(1, y: 2, z:3);
        int v5 = SomarB(1, z:3);

}

public int SomarA(int x, int y)
 {
        return (x + y);
 }

public int SomarB(int x, int y=100)
 {
        return (x + y);
 }

public int Somar(int x, int y = 100, int z = 200)
 {
        return (x + y + z);
 }

As possibilidades são grandes. Bom uso.