|
|
(7 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| {{TOCright}}
| | #REDIRECT [[ist:Classes Internas (Java)/Gatos Iteráveis]] |
| A tarefa nestes exemplos é definir um gato iterável. Esta tarefa é realizada nos exemplos 1 a 5 de formas diferentes, embora produzindo sempre o mesmo resultado (excepto onde indicado). O exemplo 6 ilustra aspectos de polimorfismo relacionado com as várias partes de um gato construído desta forma.
| |
| | |
| Iterar implica a capacidade de obter múltiplas entidades a partir de um gato. Embora seja perfeitamente possível definir iteradores independentes da linguagem Java, é mais conveniente usar os conceitos Java para iteração, pois permitem utilizar algoritmos pré-definidos para iteradores (tirando partido do polimosfismo) e utilizar a sintaxe especial ''for-each'', aplicável a entidades iteráveis e ''arrays'' (i.e., entidade primitivas com dimensão fixa).
| |
| | |
| Assim, serão implementadas duas interfaces pré-definidas em Java. A primeira das interfaces é '''java.lang.Iterable<T>''' e é implementada pelas classes que representam, em cada caso, o conceito de gato. Em geral, esta interface é implementada por qualquer entidade que representa um qualquer tipo de colecção de objectos.
| |
| | |
| A segunda interface é '''java.util.Iterator<T>''' e é implementada pelos iteradores definidos para as entidades iteráveis. Note-se que alguns dos exemplos de implementação serão internos, embora esta interface seja exterior a todas as classes.
| |
| | |
| == Caso 1: definição de duas classes independentes ==
| |
| | |
| Este exemplo apresenta o conceito de Gato como iterável, mas não disponibiliza nesse conceito nenhuma definição para o tipo do iterador. Esta situação implica que o iterador tem de ser definido depois da classe do gato estar terminada. Pode implicar ainda que a classe do gato tenha de disponibilizar uma interface pública para permitir a definição e funcionamento do iterador (sem a qual o iterador pode não ter acesso às estruturas internas do gato).
| |
| | |
| === Classe do conceito gato: Cat ===
| |
| | |
| Os métodos '''size()''' e '''part(int i)''' são utilizados pelo iterador, mas expõem aspectos da implementação internada do gato.
| |
| | |
| Note-se que o método '''iterador()''', imposto pela interface '''Iterable<T>''', retorna a um iterador para a instância da classe do gato à qual é pedido o iterador. Como as intâncias das classes do iterador e do gato não têm nenhuma relação especial, é necessário informar o iterador sobre o gato a iterar.
| |
| <java5>
| |
| import java.util.List;
| |
| import java.util.ArrayList;
| |
| import java.util.Iterator;
| |
| public class Cat implements Iterable<CatPart> {
| |
| private List<CatPart> _parts = new ArrayList<CatPart>();
| |
| | |
| public Cat(int nparts) {
| |
| for (int i = 0; i < nparts; i++)
| |
| _parts.add(new CatPart(i));
| |
| }
| |
| | |
| public int size() { return _parts.size(); }
| |
| | |
| public CatPart part(int i) { return _parts.get(i); }
| |
| | |
| public Iterator<CatPart> iterator() {
| |
| return new CatIterator(this);
| |
| }
| |
| | |
| }
| |
| </java5>
| |
| | |
| === Classe do iterador: CatIterator ===
| |
| | |
| Esta classe implementa a interface '''Iterator<T>''', em que '''T''' é uma parte do gato. A interface obriga à implementação dos métodos '''hasNext''', '''next''' e '''remove'''. Estas implementações são feitas com base no índice gerido pelo iterador e na intância de gato passada no construtor.
| |
| | |
| <java5>
| |
| import java.util.Iterator;
| |
| public class CatIterator implements Iterator<CatPart> {
| |
| Cat _cat;
| |
| int _index = 0;
| |
| public CatIterator(Cat cat) { _cat = cat; }
| |
| public boolean hasNext() { return _index < _cat.size(); }
| |
| public CatPart next() { return _cat.part(_index++); }
| |
| public void remove() { throw new UnsupportedOperationException(); }
| |
| }
| |
| </java5>
| |
| | |
| === Classe de parte de gato: CatPart ===
| |
| | |
| Esta é uma classe muito simples que serve apenas para ilustrar a construção de um gato a partir de partes de gato. Neste exemplo, não é feita nenhuma distinção entre as várias partes (em exemplos mais elaborados, o polimorfismo de inclusão vai permitir continuar a ignorar as diferenças na maior parte, se não em todos, dos casos). O único método definido (além do construtor) é o método '''toString''', para permitir obter alguma informação útil (distinguir as partes) quando se imprime um gato.
| |
| | |
| <java5>
| |
| public class CatPart {
| |
| private int _i;
| |
| public CatPart(int i) { _i = i; }
| |
| public String toString() { return "PART #" + _i; }
| |
| }
| |
| </java5>
| |
| | |
| === Aplicação exemplo ===
| |
| | |
| Esta aplicação ilustra a utilização dos conceitos acima. Note-se que o modo de iteração utilizado (''for-each'') é válido para entidades que implementem o conceito '''java.util.Iterable<T>''' e para arrays primitivos.
| |
| | |
| <java5>
| |
| public class App {
| |
| public static void main(String[] args) {
| |
| Cat cat = new Cat(5);
| |
| for (CatPart part: cat)
| |
| System.out.println(part);
| |
| }
| |
| }
| |
| </java5>
| |
| | |
| === Como Executar ===
| |
| | |
| O processo de execução é o habitual. Primeiro, é necessário compilar as classes:
| |
| | |
| javac App.java CatIterator.java Cat.java CatPart.java
| |
| | |
| Em segundo lugar, executa-se a partir da classe que contém o método '''main''':
| |
| | |
| java App
| |
| | |
| O resultado é:
| |
| | |
| <text>
| |
| PART #0
| |
| PART #1
| |
| PART #2
| |
| PART #3
| |
| PART #4
| |
| </text>
| |
| | |
| == Caso 2: reutilização de iteradores ==
| |
| | |
| Este caso é como o primeiro, i.e., temos um gato que não define nenhum iterador específico. No entanto, ao contrário do primeiro caso, onde se definiu uma classe para iterar o gato, neste caso observamos que o iterador no caso anterior apenas iterava a lista de partes do gato. Como tanto o iterador do gato (no exemplo anterior), como o iterador da lista, implementam '''Iterator<CatPart>''', é possível poupar a definição de uma classe e reutilizar o iterador da lista.
| |
| | |
| === Classe do conceito gato: Cat ===
| |
| | |
| O gato fica assim definido:
| |
| | |
| <java5>
| |
| import java.util.List;
| |
| import java.util.ArrayList;
| |
| import java.util.Iterator;
| |
| public class Cat implements Iterable<CatPart> {
| |
| private List<CatPart> _parts = new ArrayList<CatPart>();
| |
| | |
| public Cat(int nparts) {
| |
| for (int i = 0; i < nparts; i++)
| |
| _parts.add(new CatPart(i));
| |
| }
| |
| | |
| public Iterator<CatPart> iterator() {
| |
| return _parts.iterator();
| |
| }
| |
| | |
| }
| |
| </java5>
| |
| | |
| A classe '''CatIterator''' deixa de ser necessária e as restantes permanecem inalteradas.
| |
| | |
| Note-se como a reutilização de um conceito equivalente (para esta situação) permitiu ainda simplificar o código da classe gato.
| |
| | |
| === Como Executar ===
| |
| | |
| O processo de execução é o habitual. Primeiro, é necessário compilar as classes:
| |
| | |
| javac App.java Cat.java CatPart.java
| |
| | |
| A execução é exactamente como no caso anteriores.
| |
| | |
| == Caso 3: usando classes internas ==
| |
| | |
| No caso 1, o iterador de gatos era uma instância de uma classe definida especialmente para esse efeito. No caso 2, o processo de iteração era levado a cabo através de um iterador já definido (o iterador de uma lista, tal como implementado pela classe '''java.util.ArrayList<T>'''. O segundo exemplo mostrava apenas como é possível reutilizar o iterador de uma estrutura interna a um objecto para fornecer essa funcionalidade ao objecto que a contém.
| |
| | |
| Note-se que, tal como no caso 2, apenas é necessária a definição das classes '''Cat''' (para o conceito gato), '''CatPart''' (partes abstractas do gato) e '''App''' (a aplicação). A classe do iterador está contida na da classe gato. Estas duas classes são como nos casos anteriores.
| |
| | |
| === Classe do conceito gato: Cat ===
| |
| | |
| Neste exemplo, volta-se a considerar uma classe específica para a iteração, mas melhora-se a implementação da classe de iteração, por forma a não ser necessária a interface adicional de suporte (métodos '''size''' e '''part''' de gato). Neste aspecto, a classe gato é semelhante à do caso 2. A nova classe de iteração recorre ao mecanismo das classes internas Java.
| |
| | |
| <java5>
| |
| import java.util.List;
| |
| import java.util.ArrayList;
| |
| import java.util.Iterator;
| |
| public class Cat implements Iterable<CatPart> {
| |
| private List<CatPart> _parts = new ArrayList<CatPart>();
| |
| | |
| private class CatIterator implements Iterator<CatPart> {
| |
| int _index = 0;
| |
| public boolean hasNext() { return _index < _parts.size(); }
| |
| public CatPart next() { return _parts.get(_index++); }
| |
| public void remove() { throw new UnsupportedOperationException(); }
| |
| }
| |
| | |
| public Cat(int nparts) {
| |
| for (int i = 0; i < nparts; i++)
| |
| _parts.add(new CatPart(i));
| |
| }
| |
| | |
| public Iterator<CatPart> iterator() {
| |
| return new CatIterator();
| |
| }
| |
| | |
| }
| |
| </java5>
| |
| | |
| Note-se que a definição de '''CatIterator''' é agora privada da classe '''Cat''' e que apenas pode ser vista como uma implementação de '''java.util.Iterator<CatPart>'''. A interface adicional do caso 1 não é necessária neste caso, pois, como a classe do iterador é interna, dispõe de acesso ao estado do gato em iteração. Além deste aspecto, a definição da classe gato é semelhante à de casos anteriores.
| |
| | |
| === Como Executar ===
| |
| | |
| O processo de execução é o habitual. Primeiro, é necessário compilar as classes:
| |
| | |
| javac App.java Cat.java CatPart.java
| |
| | |
| Note-se que, neste caso, além dos ficheiros .class resultantes da compilação das classes indicadas, é produzido também o ficheiro '''Cat$CatIterator.class''' (correspondente à classe interna, cujo nome ao nível do código é '''Cat.CatIterator''').
| |
| | |
| A execução é exactamente como nos casos anteriores.
| |
| | |
| == Caso 4: usando classe interna a um método ==
| |
| | |
| == Caso 5: usando classe anónima ==
| |
| | |
| == Caso 6: usando classes anónimas e polimorfismo ==
| |
| | |
| == Leitura adicional ==
| |
| | |
| Ver o manual de Java, para os conceitos acima.
| |
| * http://docs.oracle.com/javase/7/docs/api/java/lang/Iterable.html
| |
| * http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
| |
| | |
| [[Category:Ensino]]
| |
| [[Category:PO]]
| |
| [[category:PO Exemplos]]
| |