(→Leitura adicional) |
(→Caso 1: definição de duas classes independentes) |
||
Line 9: | Line 9: | ||
== Caso 1: definição de duas classes independentes == | == 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); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </jav5> | ||
+ | |||
+ | === 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> | ||
+ | |||
+ | [[category:PO]] | ||
+ | [[category:Ensino]] | ||
+ | [[category:PO Exemplos]] | ||
== Caso 2: reutilização de iteradores == | == Caso 2: reutilização de iteradores == |
A tarefa nestes exemplos é definir um gato iterável.
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.
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).
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); }
} </jav5>
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>
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>
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>
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>
Ver o manual de Java, para os conceitos acima.