O documento discute interfaces, listas e listas ligadas e iteradores em programação orientada a objetos. Aborda como interfaces definem comportamentos que classes podem implementar e como classes genéricas como listas ligadas permitem armazenar diferentes tipos de elementos de forma polimórfica. Explica operações básicas em listas ligadas como inserção e remoção e como iteradores permitem percorrer listas de forma paralela.
2. Na aula anterior Polimorfismo de subtipos Classes e operações polimórficas Herança Ligação estática e ligação dinâmica Classes abstractas e classes concretas Operações abstractas Análise, desenho e implementação Dicionário do domínio Conceitos Conceitos concretos e conceitos abstractos 2009/2010 Programação Orientada por Objectos 2
3. Interfaces Definem um comportamento que as classes podem implementar Contêm apenas constantes e declarações de operações (e tipos embutidos) Classes podem implementar interfaces Uma classe pode implementar várias interfaces, embora possa derivar apenas de uma outra classe Uma interface pode estender (derivar de) outra 2009/2010 Programação Orientada por Objectos 3
4. Interfaces: definição public interface Comparable<T> { intcompareTo(T object); } public interface Queue<E> { E element(); voidadd(E e); void remove(); } 2009/2010 Programação Orientada por Objectos 4 Interface genérica. T é um parâmetro. O correspondente argumento tem de ser um tipo. Nota: A interface Queue é um pouco diferente na biblioteca do Java! Operações públicas por omissão. Operações apenas declaradas. Não se define qualquer método. Não é necessário usar o qualificador abstract.
5. Interfaces: implementação public class Rational implements Comparable<Rational> { private int numerator; private int denominator; … public intcompareTo(final Rational another) { intleftNumerator = getNumerator() * another.getDenominator(); intrightNumerator = another.getNumerator() * getDenominator(); if (leftNumerator > rightNumerator) return 1; if (leftNumerator < rightNumerator) return -1; return 0; } … } 2009/2010 Programação Orientada por Objectos 5
6. public class Rational implements Comparable<Rational> { private int numerator; private int denominator; … public intcompareTo(final Rational another){ return getNumerator() * another.getDenominator() - another.getNumerator() * getDenominator(); } … } Interfaces: implementação 2009/2010 Programação OrientadaporObjectos 6 «interface» Comparable<T->Rational> Implementação Relação de realização Comparable<T -> Rational> Rational Rational
8. Interfaces: nomes Adjectivo denotando possibilidade de realizar determinadas operações (e.g., Comparable) Nome denotando conceito cujo comportamento será implementado (e.g., Queue) 2009/2010 Programação Orientada por Objectos 8 Caso semelhante ao das classes abstractas, mas não há qualquer herança de implementação (i.e., de atributos não constantes e métodos) e uma classe que implemente a interface pode simultaneamente implementar outras interfaces.
9. Genericidade Precisa-se de classes semelhantes Com operações semelhantes Com atributos semelhantes Variando apenas em alguns tipos (e.g., o tipo dos elementos a guardar em diferentes listas) É necessário definir essas classes separadamente? 2009/2010 Programação Orientada por Objectos 9
10. Lista genérica? public class ArrayList { private Object[] elements; … } 2009/2010 Programação Orientada por Objectos 10 - elements Object ArrayList * Room
11. Lista genérica: implementação public class ArrayList<E> { private E[] elements; … } 2009/2010 Programação Orientada por Objectos 11 Classe genérica. E é um parâmetro. O correspondente argumento tem de ser um tipo. E Notação UML para classes genéricas (também conhecidas por modelos ou templates). ArrayList - elements : E [*] «bind» <E -> Room> - elements ArrayList<E->Room> Room *
12. Lista genérica: utilização publicclassFloor { privateArrayList<Room> rooms = newArrayList<Room>(); publicFloor(final intnumberOfRooms) { for (introomNumber = 1; roomNumber != numberOfRooms + 1; roomNumber++) rooms.addFirst(newRoom(roomNumber)); } publicvoid show() { while (rooms.hasNext()) out.println(rooms.next()); } } 2009/2010 Programação OrientadaporObjectos 12 Inserir novo elemento no início ou a meio da lista implica “empurrar” elementos existentes para “fazer espaço”. Para fazer isto o que é preciso?
13. Lista ligada genérica: implementação public class LinkedList<E> { Node<E> firstNode = null; Node<E> currentNode = null; … private static class Node<E> { private Node<E> nextNode; private E element; private Node(final Node<E> nextNode, final E element) { this.nextNode = nextNode; this.element = element; } } … } 2009/2010 Programação Orientada por Objectos 13 Classe embutida (nested) privada. A classe LinkedList<E> tem acesso aos membros privados de Node<E>.
14. Lista ligada genérica: notação 2009/2010 Programação Orientada por Objectos 14 E E LinkedList LinkedList - firstNode: Node<E> - currentNode: Node<E> E Node - nextNode: Node - element: E E Notações para o embutimento. Node - nextNode: Node - element: E E E LinkedList LinkedList::Node - firstNode: Node<E> - currentNode: Node<E> - nextNode: Node - element: E
15. Lista ligada genérica: utilização publicclassFloor { privateLinkedList<Room> rooms = newLinkedList<Room>(); publicFloor(final intnumberOfRooms) { for (introomNumber = 1; roomNumber != numberOfRooms + 1; roomNumber++) rooms.addFirst(newRoom(roomNumber)); } publicvoid show() { while (rooms.hasNext()) out.println(rooms.next()); } } 2009/2010 Programação OrientadaporObjectos 15 Inserir novo elemento no início ou no meio da lista não implica “empurrar” elementos existentes!
16. Lista ligada genérica: Exemplo 2009/2010 Programação Orientada por Objectos 16 rooms : LinkedList<E->Room> firstNode currentNode nextNode : Node<E -> Room> : Node<E -> Room> nextNode = null element element : Room : Room
17. Lista ligada genérica: inserir no início public class LinkedList<E> { Node<E> firstNode = null; … private static class Node<E> { … private Node(final Node<E> nextNode, final E element) { this.nextNode = nextNode; this.element = element; } } public void addFirst(final E newElement) { firstNode = new Node<E>(firstNode, newElement); } … } 2009/2010 Programação Orientada por Objectos 17
18. Lista ligada genérica: inserir no início 2009/2010 Programação Orientada por Objectos 18 rooms : LinkedList<E->Room> firstNode firstNode currentNode nextNode nextNode : Node<E -> Room> : Node<E -> Room> : Node<E -> Room> nextNode = null element element element : Room : Room newElement : Room
19. Lista ligada genérica: remover do início public class LinkedList<E> { … public void removeFirst() { if (isEmpty()) throw new NoSuchElementException(…); if (currentNode == firstNode) currentNode = currentNode.nextNode; Node<E> nextFirstNode = firstNode.nextNode; firstNode.element = null; firstNode.nextNode = null; firstNode = nextFirstNode; } … } 2009/2010 Programação Orientada por Objectos 19
20. Lista ligada genérica: remover do início 2009/2010 Programação Orientada por Objectos 20 rooms : LinkedList<E->Room> firstNode currentNode firstNode nextNode : Node<E -> Room> : Node<E -> Room> element = null nextNode = null element element : Room : Room nextFirstNode : «ref» Node<E -> Room>
21. Lista ligada genérica: inserir no fim public class LinkedList<E> { … public void addLast(final E element) { if (firstNode == null) firstNode = new Node<E>(null, element); else lastNode().nextNode = new Node<E>(null, element); } private Node<E> lastNode() { Node<E> node = firstNode; while (node.nextNode != null) node = node.nextNode; return node; } … } 2009/2010 Programação Orientada por Objectos 21
22. Lista ligada genérica: inserir no fim public class LinkedList<E> { … public void addLast(final E element) { if (firstNode == null) firstNode = new Node<E>(null, element); else { Node<E> lastNode = firstNode; while (lastNode.nextNode != null) lastNode = lastNode.nextNode; lastNode.nextNode = new Node<E>(null, element); } } … } 2009/2010 Programação Orientada por Objectos 22
23. Lista ligada genérica: inserir no fim 2009/2010 Programação Orientada por Objectos 23 rooms : LinkedList<E->Room> firstNode currentNode nextNode nextNode : Node<E -> Room> : Node<E -> Room> : Node<E -> Room> nextNode = null nextNode = null element element element : Room : Room newElement : Room lastNode : «ref» Node<E -> Room>
24. Lista ligada genérica: passar ao seguinte public class LinkedList<E> { … public E next() { if (!hasNext()) throw new NoSuchElementException(“…"); if (currentNode == null) currentNode = firstNode; else currentNode = currentNode.nextNode; return currentNode.element; } … } 2009/2010 Programação Orientada por Objectos 24
25. Lista ligada genérica: passar ao seguinte 2009/2010 Programação Orientada por Objectos 25 rooms : LinkedList<E->Room> firstNode currentNode currentNode nextNode nextNode : Node<E -> Room> : Node<E -> Room> : Node<E -> Room> nextNode = null nextNode = null element element element : Room : Room newElement : Room
26. Lista ligada genérica: notação 2009/2010 Programação Orientada por Objectos 26 1 E LinkedList Esta solução não permite percorrer a lista mais do que uma vez em paralelo! 0..1 0..1 0..1 currentNode E Node 0..1 firstNode 0..1 - element: E * nextNode 0..1
27. Lista ligada genérica: iteradores publicclassFloor { privateLinkedList<Room> rooms = newLinkedList<Room>(); publicFloor(final intnumberOfRooms) { for (introomNumber = 1; roomNumber != numberOfRooms + 1; roomNumber++) rooms.add(newRoom(roomNumber)); } publicvoid show() { while (rooms.hasNext()) out.println(rooms.next()); } } 2009/2010 Programação OrientadaporObjectos 27
29. Lista ligada genérica: notação 2009/2010 Programação Orientada por Objectos 29 E LinkedList 0..1 LinkedList.this 1 E * Node Iterator é uma classe interna (inner). As suas instâncias têm uma ligação implícita à instância da classe envolvente que as criou. A ver com pormenor mais tarde. 0..1 0..1 * Iterator currentNode firstNode 0..1 Esta solução permite percorrer a lista mais do que uma vez em paralelo! - element: E * 0..1 nextNode
30. Iteradores Permitem iterar ao longo de uma sequência de elementos, actuando sobre essa sequência A uma sequência podem associar-se vários iteradores Classes que forneçam iteradores podem ser usadas em ciclos for-each 2009/2010 Programação Orientada por Objectos 30 Mais tarde voltaremos a este assunto.
31. A reter… Interfaces Definem comportamentos (adjectivam) Classes implementam-nas Listas Listas ligadas Operações sobre listas ligadas Introdução aos iteradores 2009/2010 Programação Orientada por Objectos Página 31
32. A ler para a próxima aula… Classes relativas a colecções na API do Java Capítulos 1 a 10 e 16 do livro: Y. Daniel Liang, Introduction to Java Programming, 7.ª edição, Prentice-Hall, 2008.ISBN: 978-0-13-605966-0 2009/2010 Programação Orientada por Objectos Página 32
33. Aula 3: Sumário Interfaces Listas e listas ligadas Iteradores 2009/2010 Programação Orientada por Objectos Página 33