Você já teve interesse de conhecer como são as implementações de Listas ? (List do C#, Java)
Basicamente, as interfaces(List) definem os tipos de operações que podem ser realizadas nas Lista. Vou escrever algo bem bacana, faremos uma implementação de Lista Imutável.
Imutabilidade
Basicamente, é uma característica de um objeto permanecer o mesmo sempre. Quer saber mais sobre Imutabilidade: Bruno Nardini http://www.brunonardini.com.br/artigos/favoreca-a-imutabilidade-e-a-simplicidade
A classe String, tanto do Java quanto C# , encapsula alguns métodos de manipulação de String, como o toUpperCase() (C# = ToUpper()), que têm o objetivo de converter sua string para maiúsculo. Porém por baixo dos panos, o que acontece é você receberá uma nova instância, com o conteúdo de sua string antiga convertida para maiúsculo. (Você pode verificar isso nos links acima)
Já definido o que é Imutabilidade, vamos ao conceito básico de Listas Ligadas (Linked List). (http://www.caelum.com.br/apostila-java-estrutura-dados/listas-ligadas/#5-1-solucao-classica-de-lista-ligada)
Uma Lista Ligada é uma lista onde o elemento atual "aponta"(tem o endereço) para/do o seu próximo irmão, analisem a fotografia abaixo:
Um conceito simples, agora vamos a prática, assim podemos misturar os dois conceitos! (Imutabilidade e Linked List). No exemplo vai rolar um pouco Generics, se já sabe legal, caso não: http://en.wikipedia.org/wiki/Generic_programming#Generics_in_Java .
Primeiro, vamos criar uma interface para nossas listas, para isso, crie um projeto novo no Eclipse, dê um nome e vamos lá:
New -> Interface
public interface List{ T cabeca(); List cauda(); List adicionaNoComeco(T elemento); T pegaPosicao(int position); List removePrimeiraPosicao(); }
Bom e o que é cabeça e cauda?
Cabeça é o elemento superior de nossa lista, ou seja a head da Lista.
Cauda é todo o restante da lista, é composta por sua cabeça e outra cauda, e assim respectivamente.
Nosso método adicionaNoComeco(T elemento) recebe um parâmetro e retorna uma nova Lista com o respectivo elemento adicionado. Bem parecido com o método removePrimeiraPosicao() que remove o primeiro elemento e retorna a cauda da lista.
Bom vamos as implementações, vamos criar uma nova classe, que podemos chamar de No, ou seja, serão os respectivos nós de nossa Lista:
public class Noimplements List { private final T cabeca; private final List cauda; public No(T cabeca, List cauda) { this.cabeca = cabeca; this.cauda = cauda; } @Override public T cabeca() { return cabeca; } @Override public List cauda() { return cauda; } @Override public List adicionaNoComeco(T elemento) { return new No (elemento, this); } @Override public T pegaPosicao(int position) { if (position == 0) return cabeca(); return cauda.pegaPosicao(position - 1); } @Override public List removePrimeiraPosicao() { return cauda(); } }
Entenda:
Ao criar um No, nós receberemos a cabeça (elemento) e sua respectiva cauda (List). Fora o método pegaPosicao, o restante é bem trivial, por isso não entrarei em maiores detalhes.
pegaPosicao(T elemento)
Esse método faz uso recursivo de si próprio, ou seja, ele percorre a cauda, caso o posicao não seja 0, e recursivamente ele vai caminhando de cabeça em cabeça, das caudas, para encontrar o elemento desejado. Bem simples e objetivo.
Certo, feito isso, fica simples entender algumas coisas, a primeira de todas, como será o fim de nossa lista?
Temos que saber onde a Lista tem seu final e como o fazemos?
Faremos outra implementação de List, que agora chamaremos de Nil, será o fim de nossa lista.
public class Nilimplements List { @Override public T cabeca() { throw new RuntimeException("Lista Vazia"); } @Override public List cauda() { throw new RuntimeException("Lista Vazia"); } @Override public List adicionaNoComeco(T elemento) { return new No (elemento, this); } @Override public T pegaPosicao(int position) { throw new RuntimeException("A lista não possui elementos"); } @Override public List removePrimeiraPosicao() { throw new RuntimeException( "Impossível remover elementos de uma lista vazia"); } }
O Nil, que como dito acima, tem o objetivo de ser o fim da lista, a única coisa que podemos escrever interessante ao seu respeito é que a reescrita do método adicionaNoComeco vai retornar uma nova instância de No, ou seja, iniciaremos uma lista.
Feito isso, temos um Container, o List, que armazena valores e possui funções para alterar os dados internos, isso nos ajuda muito com a Imutabilidade, nos sentimos mais seguros e sabemos que nosso objeto não será um mutante, que pode perder/alterar seus valores em tempo de execução.
Bom galera, o conceito de hoje foi bem bacana e construtivo, é o que tenho mais feito no meu treinamento com o Jonas, aqui na Lambda3. Espero que tenha ficado claro.
Para os C# manjadores, no meu Github tem um exemplo parecido escrito em C#. Para os Javas, deixarei outro repositório no GitHub já com os testes implementados.
Qualquer dúvida ou sugestão email-me: abner.terribili@lambda3.com.br ou comente abaixo!
Valeu galera!
Nenhum comentário:
Postar um comentário