Tag: java

Java, exercício de análise

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class MyException extends Exception {
}

class main {
    static void f(int n) throws MyException {
        try {
            if (n > 0) {
                throw new MyException();
            }
            System.out.print("fl ");
        } catch (MyException e) {
            System.out.print("f2 ");
            //saida: f2
        } finally {
            System.out.print("f3 ");
            //saida: f3
        }
        System.out.print("f4 ");
        //saida: f4
    }

    public static void main(String[] args) {
        try {
            f(2);
            System.out.print("ml ");
            //saida: m1
        } catch (MyException e) {
            System.out.print("m2 ");
        }
        System.out.print("m3 ");
        //saida: m3
    }
}

assunto: classes concreta (não abstracta)
pergunta: qual o output do seguinte:

interface IMove {
    void move();
}

interface IJump extends IMove {
    default void jump() {
        System.out.println(" jump ");
    }
    int getHeight();
}

class Kanguru implements IJump {
//para se tornar numa classe concreta, tem que ter todos os métodos anteriores
    public void jump() {
    }
    public void move() {
    }
    public int getHeight() {
        return 1;
    }
}

assunto: equals, arrays, hashCode, hashSet
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class Product {

    private String id;
    private int stockQt;

    public Product(String id, int q) {
        this.id = id;
        this.stockQt = q;
    }

    public boolean sell(int n) {
        if (stockQt >= n) {
            stockQt -= n;
            return true;
        }
        return false;
    }

    @Override
    public boolean equals(Object ob) {
        if (ob == null || getClass() != ob.getClass()) {
            return false;
        }
        return id.equals(((Product) ob).id);
    }

    @Override
    public int hashCode() {
        return this.stockQt;
    }
}

public class main {

    public static void main(String[] args) {
        Product a = new Product("idA", 10);
        Set<Product> set = new HashSet<>();
        set.add(a);
        a.sell(4);
        System.out.print(" Contains? " + set.contains(a));
        //supostamente estas a comparar com o equals endereços de memória
        //saida: falso
        
        Product b = new Product("id8", 10);
        List<Product> list = new ArrayList<>();
        list.add(b);
        b.sell(4);
        System.out.print(" Contains? " + list.contains(b));
        //sendo um array..
        //saida: true
    }
}

assunto: classes derivadas, super
pergunta: qual o output do seguinte:

package recursopa2;

class Bird {

    private String name;

    public Bird(String s) {
        name = s;
    }

    @Override
    public String toString() {
        return name;
    }
}

class Swallow extends Bird {

    public Swallow(String s) {
        //line A
        super(s);
    }

    public String toString() {
        // line B
        return super.toString() + "Swallow";
    }
}

public class main {

    public static void main(String[] args) {
        Swallow objl = new Swallow(" from Africa ");
        Swallow obj2 = new Swallow(" from the islands ");
        System.out.println(objl + " " + obj2);
        //saida: from Africa Swallow from the islands Swallow
    }
}

assunto: classes derivadas
pergunta: qual o output do seguinte:

package recursopa2;

interface IMove {
    void move(); //mover 
}

interface IFly extends IMove {

    void fly(); //voar
}

class Gaivota implements IFly {

    public void move() {
        System.out.println("move");
    }

    public void fly() {
        System.out.println("fly");
    }
}

class main {

    public static void main(String[] args) {
        IMove a = new IMove();  //linha 1
        //erro: IMove, é uma interface, é abstracta 
        
        IMove[] b = new IFly[4];  //linha 2
        IFly c = new Gaivota();  //linha 3
        IMove d = new Gaivota(); //linha 4
        c.move(); //linha 5
        c.fly(); //linha 6
        d.fly(); //linha 7
        //erro: o método fly nao faz parte de IMove
        
        d.move(); //linha 8
        c = d; //linha 9
        //erro: não da para coverter tipos diferentes
        
        d = c; //linha 10
    }
}

assunto: máquina de estados, state machine
pergunta: pretende desenvolver uma nova versão da classe MTThread sob a forma de uma máquina de estados orientada a objectos. Recorra, para o efeito, ao padrão estudado nas aulas laboratoriais e aplicado ao trabalho prático de modo a que uma thread passe a ser uma instância de uma classe que, entre outros atributos, inclua o seu estado actual e tire partido do polimorfismo ao nível dos estados.

package recursopa2;

class MTThread {

    public static enum Const {
        WAII_START, WAII_TO_BE_SCHEDULED, TERMINATED,
        YELD_INVOKED, RUNNING, SCHEDULE_COMPLETED, UNBLOCKED,
        SLEEP_COMPLETED, BLOCKED, SLEEPING, SLEEP_INVOKED
    };
    private Const situation;
    private Data data;

    // Some hidden stuff you don't have to worry about
    //(constructors, getters, ...J
    /* ... */
    public Const getSituation() {
        return situation;
    }

    public void start() {
        if (situation == Const.WAII_START) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void schedule() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void doSomething() {
        if (situation == Const.RUNNING) {
            Const result = data.doSomething();
            switch (result) {
                case YELD_INVOKED:
                    situation = Const.WAII_TO_BE_SCHEDULED;
                    break;
                case BLOCKED:
                    situation = Const.BLOCKED;
                    break;
                case SLEEP_INVOKED:
                    situation = Const.SLEEPING;
                    break;
                case TERMINATED:
                    situation = Const.TERMINATED;
                    break;
                default:
                    break;
            }
        }
    }

    public void scheduleCompleted() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void unblocked() {
        if (situation == Const.BLOCKED) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void sleepCompleted() {
        if (situation == Const.SLEEPING) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }
}

resposta:

interface IStates {
    Const getSituation();
    IStates start();
    IStates schedule();
    IStates doSomething();
    IStates scheduleCompleted();
    IStates unblocked();
    IStates sleepCompleted();
}

assunto: máquina de estados, state machine
pergunta: implemente uma classe StateAdapter que implemente a interface IStates e a partir da qual derivam todos os estados da nova versão da máquina de estados MTThread

public class StateAdapter implements IStates {
    @Override
    public Const getSituation() {
        return this;
    }

    @Override
    IStates start() {
        return this;
    }

    @Override
    IStates schedule() {
        return this;
    }

    @Override
    IStates doSomething() {
        return this;
    }

    @Override
    IStates scheduleCompleted() {
        return this;
    }

    @Override
    IStates unblocked() {
        return this;
    }

    @Override
    IStates sleepCompleted() {
        return this;
    }
}

assunto: máquina de estados, state machine, IStates
pergunta: implemente uma classe que representa o estado em que a thread se encontra bloqueada na nova versão da máquina de estados MTThread

class Blocked extends StateAdapter{
    @Override
    IStates unblocked(){
        return new WaitToBeScheduled();
    }
}

assunto: máquina de estados, state machine
pergunta: As classes Defender e Forward representam jogadores de futebol, sendo ambas derivadas da classe Player. A classe Club contém uma coleção de jogadores que podem ser do tipo Defender ou Forward. A classe Club permite acrescentar jogadores e saber o número de jogadores que contém. Escreva o código necessário para que a criação de objetos do tipo Player seja feita utilizando o padrão Fábrica de Objetos e complete a função addPlayer() da classe Club, utilizando este padrão.

package recursopa2;

import java.util.ArrayList;
import java.util.List;

enum PlayerTypes {
    DEFENDER, FORWARD
}

abstract class Player {
    private String name;

    public Player(String name) {
        this.name = name;
    }
    //...
}

class Defender extends Player {
    public Defender(String name) {
        //...
    }
    //...
}

class Forward extends Player {
    public Forward(String name) {
        //...
    }
    //...
}

class Club {
    private List<Player> players = new ArrayList<>();
    //...

    public void addPlayer(PlayerTypes type, String name) {
        // Fazer : usar a fabrica de objetos do tipo Player
    }

    public int getNumPlayers() {
        return players.size();
    }
}

resposta:

 public void addPlayer(PlayerTypes type, String name) {
  switch (type) {
            case DEFENDER:
                players.add(new Defender(name));
                break;
            case FORWARD:
                players.add(new Forward(name));
                break;
        }
}

assunto: PropertyChangeListener, propertyChange
pergunta: A classe ClubPanel faz parte do interface de utilizador gráfico para objetos de Club, tendo o objetivo de mostrar o número de jogadores do clube, sempre atualizado. Acrescente o necessário à classe ClubPanel de modo a cumprir este objetivo

package recursopa2;

import java.beans.PropertyChangeEvent;

class ClubPanel extends VBox {

    private ObservableClub modelObs;// ligacao ao modelObs
    private Label nPlayers;

    public ClubPanel(ObservableClub model) {
        this.modelObs = model;
        nPlayers = new Label("N. players " + modelObs.getNumPlayers());
        getChildren().addAll(nPlayers);
        setSpacing(5);
        setPadding(new Insets(10, 10, 10, 10));
        setAlignment(Pos.CENTER);
        modelObs.addPropertyChangeListener(this);
    }

    //resposta:
    private void updateNumberOfPlayers(){
        nPlayers.setText("N. players" + modelObs.getNumPlayers());
    }
    @Override
    public void propertyChange(PropertyChangeEvent ev){
        updateNumberOfPlayers();
    }
}

assunto: máquina de estados, state machine
pergunta: Idealize um diagrama que represente a máquina de estados MTThread de forma adequada, com atribuição de nomes aos estados e às transições/métodos coincidentes com os da listagem. Deve representar todas as transições que podem ocorrer entre os estados. Descreva este diagrama de forma textual seguindo o formato usado no seguinte exemplo (estado [condição] => próximo estado):

e

package recursopa2;

class MTThread {

    public static enum Const {
        WAII_START, WAII_TO_BE_SCHEDULED, TERMINATED,
        YELD_INVOKED, RUNNING, SCHEDULE_COMPLETED, UNBLOCKED,
        SLEEP_COMPLETED, BLOCKED, SLEEPING, SLEEP_INVOKED
    };
    private Const situation;
    private Data data;

    // Some hidden stuff you don't have to worry about
    //(constructors, getters, ...J
    /* ... */
    public Const getSituation() {
        return situation;
    }

    public void start() {
        if (situation == Const.WAII_START) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void schedule() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void doSomething() {
        if (situation == Const.RUNNING) {
            Const result = data.doSomething();
            switch (result) {
                case YELD_INVOKED:
                    situation = Const.WAII_TO_BE_SCHEDULED;
                    break;
                case BLOCKED:
                    situation = Const.BLOCKED;
                    break;
                case SLEEP_INVOKED:
                    situation = Const.SLEEPING;
                    break;
                case TERMINATED:
                    situation = Const.TERMINATED;
                    break;
                default:
                    break;
            }
        }
    }

    public void scheduleCompleted() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void unblocked() {
        if (situation == Const.BLOCKED) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void sleepCompleted() {
        if (situation == Const.SLEEPING) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }
}

resposta:

States:
WAIT_START, WAIT_TO_BE_SCHEDULED, 
TERMINATED, RUNNING, BLOCKED, SLEEPING

Transitions:
WAIT_START
start()=>WAIT_TO_BE_SCHEDULED
WAIT_TO_BE_SCHEDULED
schedule()=>RUNNING
TERMINATED
RUNNING
doSomething()[result = YELD_INVOKED] => WAII_TO_BE_SCHEDULED
doSomething()[result = BLOCKED] => BLOCKED
doSomething()[result = SLEEP_INVOKED] => SLEEPING
doSomething()[result = TERMINATED] => TERMINATED
scheduleCompleted() => WAII_TO_BE_SCHEDULED
BLOCKED
unblocked() =>WAII_TO_BE_SCHEDULED
SLEEPING
sleepCompleted() =>WAII_TO_BE_SCHEDULED

Tags : ,

Java, exercício de análise

assunto: equals, hashcode e colecções
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

class Aluno{
    private String nome;
    private int codigo;

    public Aluno(String nome, int codigo){
        this.nome = nome;
        this.codigo = codigo;
    }

    public boolean equals(Object ob){
        if(!(ob instanceof Aluno)) return false;
        //o equals só exige que tenham o mesmo nome
        return nome.equals(((Aluno)ob).nome);// (Aluno) é um cast importante, por ser Object
    }
    
    public int hashCode(){
        //vai retornar o código do aluno
        return this.codigo;
    }   
}
//o equals e o hashCode estão mal feitos/compativeis (não está bem planeado)
//eles deviam ser compativeis, pois cada um pergunta por uma coisa diferente
//o hashCode devia retornar  os mesmo ou um sub conjunto dos membros do equals

class main{
     public static void main(String[] args) {

        Set<Aluno> conjunto = new HashSet<>(); 
        //HashSet (se são iguais) se:
        //para ver se está contido, uso o equals e o hashCode
        //se o hashCode for diferente acabou
        //se o hashCode for igual vai ver se o equals diz que sim ou que não
        //HashSet, não deixa acrescentar elementos que ele ache que já tem
        //não permite/recusa assim repetições
        
        Map<Aluno,Integer> mapa = new HashMap<>();
        //HashMap
        //não deixa que existam chaves iguais 
        //(compara a chave do map, primeiro testa o hashcode depois o equals)
        //vai verificar se existe alguma chave igual, se o hashCode é o mesmo
        //se for só deixa entrar alterando o valor da chave que está a ser usada
        
        List<Aluno> lista = new ArrayList<>();
        //ArrayList
        //acrescenta tudo o que lhe dado, e considera que contém
        //e só usa o equals para verificar, mas deixa sempre acrescentar
        
        conjunto.add(new Aluno("aaa", 2)); //fica, é o primeiro
        conjunto.add(new Aluno("aaa", 2)); //não fica, tem o mesmo nome, usado o equals
        conjunto.add(new Aluno("aaa", 4)); //fica, não existe nenhum com o mesmo  hashCode
        conjunto.add(new Aluno("bbb", 2)); //hashCode igual, vamos ver o equals se dá igual, fica

        mapa.put(new Aluno("aaa", 2),1); //fica é o primeiro, mas depois saiu
        mapa.put(new Aluno("aaa", 2),1); //fica, é igual, mas sai o primeiro
        mapa.put(new Aluno("aaa", 4),1); //fica, a chave/hashCode é diferente: "aaa", 4, nem sequer usa o equals
        mapa.put(new Aluno("bbb", 2),1); //o hashCode é igual, mas usa o equals que é diferente, fica

        lista.add(new Aluno("aaa", 2)); //fica é i primeiro
        lista.add(new Aluno("aaa", 2)); //fica, mesmo que sejam iguais, aceita sempre 
        lista.add(new Aluno("aaa", 4)); //fica 
        lista.add(new Aluno("bbb", 2)); //fica
        
        System.out.print(conjunto.size() + " "); // 3
        System.out.print(mapa.size() + " "); // 3
        System.out.println(lista.size()); //4

        Aluno a = new Aluno("bbb", 3); 
        System.out.print(conjunto.contains(a) + " "); 
        //perguntar se o conjunto tem o "bbb", 3
        //o conjunto tem o "bbb" mas não tem o código 3
        //assim o cojunto vai ver primeiro o hashCode, é diferente
        //logo não contem, logo a resposta dá false
        
        System.out.print((mapa.get(a) != null) + " "); 
        //o mapa.get(a), tem lá um "bbb" com código 2
        //mas o a tem código 3
        //não existe nenhum hashcode 3, , resposta dá false
        
        System.out.println(lista.contains(a));   
        //a lista só vai ver o equals
        //o equals neste caso só compara o nome
        //, e a resposta dá true
     }
} 
Tags : ,

Java, exercício de análise

assunto: arraylist, equals
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.List;

class Inteiro {
    private int i;

    public Inteiro(int i) {
        this.i = i;
    }

    public void setVal(int i) {
        this.i = i;
    }

    public int getVal() {
        return i;
    }

    public String toString() {
        return "" + i;
    }
}

class main {

    public static void main(String[] args) {
        List<Inteiro> listaInteiros = new ArrayList<>();
        //criado um arraylist de listaInteiros
        
        Inteiro i = new Inteiro(10);
        Inteiro j = new Inteiro(10);

        System.out.println(i == j);
        //saida: falso
        //porque estão em referências diferentes
        
        System.out.println(i.equals(j));
        //saida: falso
        //o equals faz a comparação que nos programamos lá dentro
        //por exemplo comparar conteudos
        //mas o equals não foi definido, e não dá erro porque
        //está a usar a do object, class Inteiro extends object
        //e a equals no object considera dois objetos iguais
        //se tiverem o mesmo endereço

        listaInteiros.add(i);
        listaInteiros.add(j);

        j = i;
        //j refere o i
        
        j.setVal(2);
        //o primeiro elemento do array list fica 2
        
        System.out.println(i);
        //saida: 2
        
        System.out.println(j);
        //saida: 2
        
        System.out.println(listaInteiros.get(0));
        //saida: 2
        
        System.out.println(listaInteiros.get(1));
        //saida: 10
    }
}
Tags : ,

Java, exercício de análise

Desenvolva a classe Artista tendo em consideração os seguintes requisitos:

Assuma que a classe Artista herda as características encapsuladas pela classe Pessoa (atenção, não a desenvolva… assuma apenas que já existe);
resposta: Artista extends Pessoa

Assuma que Pessoa possui o atributo privado nomeCivil e que não existe qualquer getter correspondente;
resposta:

Assuma que Pessoa apenas pode ser instanciada fornecendo o nome civil da pessoa encapsulada;
resposta:

Assuma que Pessoa possui os métodos int hashCode(), boolean equals(Object o) e String toString() adequadamente redefinidos, sabendo que duas instâncias de Pessoa são iguais quando possuem os mesmos nomes civis (a utilização de maiúsculas e minúsculas é irrelevante).
resposta:

A classe Artista possui, além do atributo herdado de Pessoa, o atributo nomeArtistico;
resposta: No artista, o construtor tem que receber o nome, e tem que se fazer super do nomecivil

O método boolean equals(Object o) da classe Artista deve garantir que uma instância desta classe é considerada igual a outro objecto quando este último é do tipo Artista e possui o mesmo nome civil e o mesmo nome artístico (a utilização de maiúsculas e minúsculas é irrelevante);
resposta: a classe artista que deriva, sabemos que o equals da pessoa exisge um nome civil, não temos acesso ao nomecivil, não existe getter, assim tem que se construir o equals da classe derivada, return super.equals e a exisgência da igualdade do nome artistica. não esquecer do instanceof artista

A classe Artista deve possuir um método int hashCode() adequado;
resposta: super hashCode

O método String toString() da classe Artista deve retornar uma string em que o nome civil aparece entre parêntesis depois do nome artístico;
resposta: super.toString() + nomeDoArtista

As linhas de código “oo.writeObject(artista);” e “(Artista)oin.readObject();”, sabendo que oo é do tipo ObjectOuputStream, oin do tipo ObjectInputStream e artista do tipo Artista, não devem gerar qualquer tipo de exceção relacionada com a natureza de artista.
resposta: para as classes implementarem serializer, para a escrita de ficheiros não terem problemas

Tags : ,

Java, exercício de análise

assunto: hierarquia, classes, interface, derivadas
pergunta: qual o output do seguinte:

package recursopa2;

interface IPodeDeslocar {

    void vira(double angulo);

    void defineVelocidade(double v);
}

interface IPodeCaminhar extends IPodeDeslocar {

    void caminha();
}

interface IPodeCorrer extends IPodeCaminhar {

    void corre();
}

interface IPodeVoar extends IPodeDeslocar {

    void voa(double altitude);
}

class Felino implements IPodeCorrer {

    public void corre() {
    }
    //está mal falta mas outras três 
    //para ser concreta e não precisar do abstract
    //precisa: caminha, defineVelocidade, vira
}

abstract class AveRapina implements IPodeVoar {

    public void voa(double a) {
    }
    //para ser concreta precisa do vira, defineVelocidade
    //mas é abstract e não precisa
}

class Tigre extends Felino {
    //se corrigir acrescentado em  Felino
    //caminha, defineVelocidade, vira
    //assim em Tigre devemos implemntar todas
    //corre, caminha, defineVelocidade, vira
    //e sem restringir a visibilidade, isto é
    //mantendo public void corre() ...
}

class Avestruz implements IPodeCorrer {

    public void vira(double angulo) {
    }

    public void defineVelocidade(double v) {
    }

    public void caminha() {
    }

    public void corre() {
    }
    //está correcta este concretização
}

class Aguia extends AveRapina implements IPodeCaminhar {

    public void vira(double angulo) {
    }

    public void defineVelocidade(double v) {
    }

    public void caminha() {
    }
    //aguia deriva de AveRapina
    //tem por via do implements: 
    //caminha, vira, defineVelocidade
    //tem pelo extends da sua derivada abstract 
    //deveria ter voa, mas a AveRapina é asbtract
    //logo esta classe implementa tudo
}

class Main {

    public static void main(String args[]) {
        IPodeDeslocar d1[] = new IPodeDeslocar[10];
        //não tem erro
        //podemos criar arrays dinâmicos para interfaces

        d1[0] = new AveRapina();
        //erro: não se pode criar um objecto de uma classe abstracta
        //podem existir referências, objetos não

        d1[0].voa(10.5);
        //erro, d1 é uma referencia para IPodeDeslocar
        //mas o IPodeDeslocar não tem o método voa

        d1[1] = new Avestruz();

        Avestruz av = d1[1];
        //erro, uma referências para  derivada não pode receber
        //uma referencia para o topo da hierarquia

        IPodeDeslocar t1 = new Tigre();

        IPodeCorrer t2 = t1;
        //t2=t1, siginifca o mais abaixo receber o mais acima
        //IPodeDeslocar é o topo, IPodeCorrer está abaixo
        //não funciona. 

        t1 = t2;
        //o de cima pode receber o debaixo
        //IPodeDeslocar é o topo, IPodeCorrer está abaixo

        Tigre t2 = new Felino();
        //erro, porque Tigre deriva de Felino
        //uma referência para a derivada não pode receber a da base
        //só a referência para base é que podia receber a derivada

        Aguia ag = new Aguia();
        AveRapina ar = ag;
        //aguia deriva de aveRapina
        //aveRapina está mais acima pode então receber
        //o que está mais abaixo

        ar.caminha();
        //não faz parte das funções que desaguam..

        IPodeCaminhar aguia = new Aguia();
        //sim porque Ague implementa IPodeCaminhar

        IPodeCorrer tigre = new Tigre();
        //sim IPodeCorrer está na linha acima da hierarquia

        tigre = aguia;
        //erro, porque tigre está mais abaixo na hierarquia
        //IPodeCaminhar está acima não pode ser dado ao mais abaixo

        aguia = tigre;
        //IPodeCorrer está acima e pode ser dado ao mais abaixo
        //ao contrário já dá
                
        IPodeCaminhar ag2 = (AveRapina) aguia;
        //não está na mesma linha 
        
        IPodeCorrer t3 = (Felino) tigre;
    }
}
Tags : ,

Java, exercício de análise

assunto: interfaces, classes, heranças, métodos, classes concretas, classes abstractas


pergunta: qual o output do seguinte:

package recursopa2;

interface IA {
    String getA();
}

interface IB extends IA {
    //extends, deriva de IA
    int getB();
}

interface IC {
    int getC();
}

class D implements IB, IC {
    //implements. tem que ter todos os métodos
    //mas sendo abstract não precisa
    private String a;
    private int b, c;

    public D(String a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public String getA() {
        return a;
    }

    public int getB() {
        return b;
    }

    public int getC() {
        return c;
    }

    public void setA(String a) {
        this.a = a;
    }

    public void setB(int b) {
        this.b = b;
    }

    public void setC(int c) {
        this.c = c;
    }

    public boolean equals(Object o) {
        if (o == null || !(o instanceof D)) {
            //se a referência for nula ou se não for instanceof
            return false;
        }
        //return a.equalsIgnoreCase(o.getA());
        //o o não sabe da referencia do getA()
        //resolução do erro:
        //return a.equalsIgnoreCase(((D)o).getA());
        //resolução:
        return a.equalsIgnoreCase(((D) o).getA());
    }
}

class E extends D {
    //extends, deriva de D

    public E(String a, int b, int c) {
        //1º vai ser chamado o construtor da base
        //mas o construtor da base não tem valores por omissão

        //setA(a);
        //setB(b);
        //setC(c);
        //resolução:
        super(a, b, c);
    }
}

class F extends E {
    //extends, deriva de E
    private double d;

    public F(String a, int b, int c, double d) {
        //setA(a);
        //setB(b);
        //setC(c);
        //resolução:
        super(a, b, c);
        this.d = d;
    }

    public double getD() {
        return d;
    }

    public boolean equals(Object o) {
        if (o == null || !(o instanceof F)) {
            return false;
        }
        //return a.equalsIgnoreCase(o.getA()) && b == o.getB() && c == o.getC();
        //porque o é object, não conhece o getA, getB, getC, e o a é privado da base
        //e não temos qualquer acesso
        //resolução:
        return getA().equalsIgnoreCase(((F)o).getA()) 
                && getB() == ((F)o).getB() 
                && getC() == ((F)o).getC();
    }
} 

class main {

    public static void main(String args[]) {
        IB a = new E("abc", 1, 1);
        //classe E dreviva de D
        //D implementa IB e IC
        //assim a classe E está na linha de herança de IB
        //classe E está na descendencia de IB
        //uma referencia para o IB pode referir um objecto E
        
        D b = new F("abc", 1, 1, 2.2);
        //classe F deriva de E
        //e E deriva de B
        //F está na linha de descendencia de D
        //pode então referir um objecto de F
        
        
        IA c = new E("abc", 3, 3);
        //classe E deriva de D
        //D implementa IB, 
        //IB que deriva de IA
        //logo E está na descendencia de IA
        
        //IB d = new IB();
        //dá erro
        //criar um objeto de uma interface
        //com funções abstractas 
        //não é possivel
        
        IC e = new F("ddd", 4, 4, 4.4);
        //F deriva de E
        //E deriva de D
        //D implementa IC
        //F está na descendencia de IC
        //F é uma classe concreta

        IA r1[] = new D[5];
        //criar um array de referências new D[5];
        //D é uma classe abstracta  
        //não se pode criar objetos da classe D
        //mas podemos criar arrays de referências para D
        //mas que depois se refere a objectos de classes
        //derivadas de D mas que são concretas
        //assim, podemos criar arrays de referências para
        //classes abstractas
        //e IA está na herança da linha para cima 
        
        IA r2[] = new IB[5];
        //tambem se pode criar arrays para referências
        //de interfaces, porque se trata de arrays 
        //de referências, e essas referências 
        //vão ser objectos de classes concretas
        //e que implementam directa ou indirectamente
        //este interface 
        //e IA está na linha de herança de IB
        
        
        //IB r3[] = new IA[5];
        //dá erro
        //porque estamos a observar a herança ao contrário
        //o IA é que é a base de IB
        //a derivada a receber a base não
        
        IC r4[] = new IC[5];
        //um array para referêncas para interfaces new IC[5]
        //e é uma classe concreta

        System.out.println(a);
        System.out.println(b);
        
        System.out.println(a.equals(b));
        //a é um objecto da classe E
        //o a chama o equals, 
        //o a é da classe E
        //a classe E não tem o equals
        //mas a classe E deriva de D que tem
        //vai ter a versão herdada
        //e também
        //b é um objecto da classe F
        //f é instanciaof de D (é derivada da derivada de D)
        //e na comparação interessa o getA que é a string "abc"
        //resultado: true
        
        System.out.println(b.equals(a));
        //b é uma objecto   da classe F
        //vai ser chamado o equals da classe F
        //membroA e membroB e membroC sejam iguais
        //o a é um objecto de E
        //E é instanceof D
        //e por esse motivo não faz mais nada
        //resultado: false
        
        //o (o instanceof F)
        //não garante uma simetria de igualdade
          
        System.out.println(c.equals(b));
        //c é uma objecto da classe E
        //E, em um equals que exige  
        //que o argumento seja (o instanceof D)
        //e D tem que getA, string, seja igual
        //resultado: true
        
        System.out.println(c.getA());
        //resultado: abc
        
        //System.out.println(e.getA());
        //tem erro 
        //o e é uma referencia para IC
        //o IC só tem o método getC
        //quem tem o getA é o interface IA
    }
}
Tags : ,

Java, exercício de análise

assunto: interfaces, funções abstracta, derivadas
e funções default: não sou obrigado a redefinir, não é abstracta, tem uma implementação por omissão
e funções static

pergunta: qual o output do seguinte:

package recursopa2;

interface Pagamento {
    void receber();
    void darTroco();
}

abstract class Parquimetro implements Pagamento {
    private String cidade;

    Parquimetro(String s) {
        cidade = s;
    }

    abstract void calcula();

    void calcula2() {
    }
}

interface RegistaVisita {
    void registaVisita();
}

//ser derivada de Parquimetro e "do tipo" RegistaVisita 
// "do tipo" -> impementa a interface RegistaVisita
// "ser concreta", todos os métodos têm que ser concretizados 
//e o membro cidade ser inicializada com "Coimbra"
//assim,
//se forem default ou static não é preciso/não é obrigatório redefinir 
//se a base, for do extendes, e estiver concretizada, não preciso de a redefinir  void calcula2()
//os métodos das outras classes de que esta deriva ou que desagua 
class ParquimetroCoimbra extends Parquimetro implements RegistaVisita {
    public ParquimetroCoimbra() {
        super("Coimbra");
    }
    void calcula() {
    }
    public void registaVisita() {
    }

    public void receber() {
    }

    public void darTroco() {
    }
}

//public class main
class main {
    public static void main(String[] args) {

    }
}

assunto: equals, arrays
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.List;

class A {
    int n;
    A(int nn) {
        n = nn;
    }
    //não tem uma redefinição do equals
    //tem apenas a do object
}

class B extends A {
    B(int nn) {
        super(nn);
    }
    public boolean equals(B obj) {
        return true;
    }
    //"trocar", e podem coexistir
//    public boolean equals(Object obj) {
//        return true;
//    }
}

class main {

    static public void main(String[] args) {
        A r1 = new A(10);
        A r2 = new A(10);
        A r3 = new B(10);
        A r4 = new B(10);

        System.out.println("r1.equals(r2) " + r1.equals(r2));
        //a classA não tem o seu equals, herda do object
        //assim os objectos estão em diferentes endereços
        //saida: false

        System.out.println("r3.equals(r4) " + r3.equals(r4));
        //a classeB tem um equals
        //r3 equals r4, r3 chama a equals através de uma referência de r3 para A
        //vai chamar a equals que A conhece, e A que a conhece é da object
        //e em A não existe uma redefinição da equals
        //saida: false

        //mas para ser true era "trocar"
        //r3 invoca a função equals que conhece
        //que é o equals da object
        //mas o polimorfismo como aponta para o objecto do tipo B
        //e assim sendo vai buscar a versão da b "trocar"
        
        List<B> list = new ArrayList<B>();
        B b1 = new B(4);
        B b2 = new B(4);
        list.add(b1);
        list.add(b2);
        System.out.println("list contem new B(4)? " + list.contains(new B(4)));
        //o contains no array, vai pegar no objecto e vai fazer o equals 
        //com os que já lá estão, e o array lista usa apenas a equals do object
        //que compara referências, e por esse motivo diz que não está lá
        //saida: false
    }
}

assunto: excepções

pergunta: qual o output do seguinte:

package recursopa2;

class EstaExcepcao extends Exception {
}

class main {
    static void f() throws EstaExcepcao {
        try {
            System.out.println("Ponto 1");
            throw new EstaExcepcao();
            //saida: ponto 1
            
            //System.out.println("AAAAA"); //se existir dá erro
            //depois do lançamento da excepção dá sempre erro 
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 2");
            //saida: ponto 2
            
            throw e;
            //vai ser relançada
        } finally {
            System.out.println("Ponto 3");
            //saida: ponto 3
        }
         //System.out.println("BBBB"); //se existice
         //como houve erro nunca iria ser executada, por exemplo
         //não havendo o throw
    }

    public static void main(String[] args) {
        try {
            f(); 
            // f() sai em erro, vai fazer o catch
            System.out.println("Ponto 4");
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 5");
            //saida: ponto 5
        } catch (Exception e) {
            System.out.println("Ponto 6");
        }
        System.out.println("Ponto 7");
        //saida: ponto 5
    }
}
Tags : ,

Java, exercício de análise

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class InteiroSomaRaizesQ {

    static private double somaRaizesQuadradas = 0;
    private double n;

    public InteiroSomaRaizesQ(String n) throws Exception {
        try {
            try {
                this.n = Double.parseDouble(n);
                //Double.parseDouble, se for bem formado do tipo 4.0
            } catch (NumberFormatException e) {
                //NumberFormatException, como é o caso de A.0
                return;
            }
            if (this.n < 0) {
                throw new Exception();
            }
            somaRaizesQuadradas += Math.sqrt(this.n);
        } finally {
            System.out.print("f1 ");
            //acontece sempre quer o if corra bem quer corra mal
        }
    }

    public static void main2(String[] args) {
        System.out.print("m1 ");
        //saida: m1
        
        try {
            new InteiroSomaRaizesQ("4.0");
            //somaRaizesQuadradas = 2
            //saida: f1, correu bem passa ao seguinte
            
            new InteiroSomaRaizesQ("A.0");
            //saida: f1, termina em paz
            
            new InteiroSomaRaizesQ("9.0");
            //somaRaizesQuadradas = 2+3
            //saida: f1, correu bem passa ao seguinte
            
            new InteiroSomaRaizesQ("-4.0");
            //acontece throw new Exception();
            //saida: f1, mas correu mal, 
            //não faço mais nada no try
            
            new InteiroSomaRaizesQ("9");
        } catch (Exception e) {
            System.out.print("e1 ");
            //saida: e1
            
            return;
        } finally {
            System.out.print("f2: " + somaRaizesQuadradas);
            //saida: f2
            //saida: 5
        }
    }
}
//para testar
public class main {
    public static void main(String[] args) {
        InteiroSomaRaizesQ.main2(args);
    }
}
Tags : ,

Java, exercício de análise

assunto: máquina de estados, padrão comando

ou

pergunta: qual o output do seguinte:

package recursopa2;

class Semaforo {

    static final int TEMPO_VERDE = 4, TEMPO_VERMELHO = 4, TEMPO_AMARELO = 1;
    private int tempo;
    private String estado;
    private String estadoAoLigar;

    public Semaforo() {
        tempo = 0;
        estado = "desligado";
        estadoAoLigar = "vermelho";
    }

    public void passaTempo() {
        if (estado.equalsIgnoreCase("desligado")) {
            return;
            //se for igual a desligado, não faz nada
        }
        tempo--;
        //se for diferente a desligado
        if (tempo > 0) {
            return;
            //se fo tempo for positivo, não faz mais nada
        }
        //se for == 0, então..
        if (estado.equalsIgnoreCase("vermelho")) {
            estado = "verde";
            tempo = TEMPO_VERDE;
        } else if (estado.equalsIgnoreCase("verde")) {
            estado = "amarelo";
            tempo = TEMPO_AMARELO;
        } else if (estado.equalsIgnoreCase("amarelo")) {
            estado = "vermelho";
            tempo = TEMPO_VERMELHO;
        }
    }

    public void desliga(String ligarEm) {
        if (estado.equalsIgnoreCase("desligado")) {
            return;
        }
        //se estiver ligado, então..
        estadoAoLigar = ligarEm;
        estado = "desligado";
        tempo = 0;
    }

    public void liga() {
        if (!estado.equalsIgnoreCase("desligado")) {
            return;
        }
        //se estiver desligado, então..
        estado = estadoAoLigar;
        if (estado.equalsIgnoreCase("vermelho")) {
            tempo = TEMPO_VERMELHO;
        } else if (estado.equalsIgnoreCase("verde")) {
            tempo = TEMPO_VERDE;
        } else if (estado.equalsIgnoreCase("amarelo")) {
            tempo = TEMPO_AMARELO;
        }
    }

    public String toString() {
        return estado + "   " + tempo;
    }
}

//para testar
public class main {

    public static void main(String[] args) {
        Semaforo s = new Semaforo();
        s.desliga("ligado");
        s.liga();
        s.passaTempo();
        System.out.println(s.toString());
    }
}

perguntas, parte I:
____ É suficiente definir três classes concretas e tipo(s) base destas classes (classe e/ou interface)
resposta: não, temos quatro estados

____ É suficiente definir quatro classes concretas sem qualquer característica em comum
resposta: não, são derivadas na mesma base

____ Conceitos como “Vermelho” ou “Verde” representam métodos
resposta: não, são classes

____ Conceitos como “PassaTempo”, “Liga” ou “Desliga” representam métodos
resposta: sim

____ Todas as classes que representam os estados dispõem de implementações (vazias ou não) de todos os métodos que representam as acções a que o semáforo tem que responder
resposta: ou seja em todos os estados temos implementações vazias ou não, de liga ou desliga, sim verdadese não temos o que interessa, temos estão o return this (o vazio)

____ Três é o número mais adequado de métodos declarados na classe abstracta de base ou na interface comum
resposta: verdade, são três

____ As implementações dos métodos definidos na classe abstracta de base ou na interface comum podem modificar os dados e/ou devolver uma referência para o objecto que representa o estado actual
resposta: é verdade. “podem modificar os dados, e não retornam o estado em que ficamos”

____ Apenas um dos métodos (representando uma transição na máquina de estados) declarados na classe abstracta de base ou na interface comum necessita de receber um argumento
resposta: é verdade, que é o String ligarEm

perguntas, parte II:
Conceitos como “PassaTempo”, “Liga” ou “Desliga” representam ____________________ (métodos/classes)
resposta: na máquina de estados eram métodos, no padrão comando são classes
arranjam-se objectos que embrulham estas acções (classes que representam comandos simples, para haver uma evolução), logo elas vão ser classes

As classes que representam os comandos concretos implementam um interface ou derivam de uma mesma classe abstracta. Indique os métodos desse tipo base abstracto ____________________________________
resposta: os métodos são o execute (executar) e o undo (refazer)

O membro “estadoAoLigar” da classe Semaforo da listagem anterior deveria ser membro de que classe da hierarquia de comandos.
resposta: no comando correspondente ao desligar

O argumento “ligaEm” da classe Semaforo da listagem E deveria ser membro da classe ____________ da hierarquia de comandos.
resposta: “ligaEm” vai ser gravado na classe desliga
quando queremos por em padrão comando um método que leva argumentos, esses argumentos também são passados ao construtor do comando e são membros do objeto comando, e ficam lá gravados dentro
“os argumentos com que as funções são chamadas, quando embrulhamos a função com um comando, esses argumentos ficam gravados na classe que representa aquela acção, que representa aquele comando”

perguntas, parte III:
a classe semáforo deve implementar a interface PropertyChangeListener
resposta: não, pois a classe semáforo é a nossa lógica/dados. Os observadores (objectos da vista) que estão do lado da vista é que implementam o PropertyChangeListener

a classe semáforo deve ser derivada de PropertyChangeSupport ou referida por uma classe derivada de PropertyChangeSupport
resposta: verdade, a classe semáforo vai ser derivada de PropertyChangeSupport

o objecto painel desenho pode ser uma instância de uma classe derivada de PropertyChangeSupport
resposta: não, o painel de desenho não tem nenhum membro de PropertyChangeSupport, ele regista-se como observador, ele tem um observador lá dentro

o objecto painelDesenho pode ser instância de uma classe que não implementa a interface PropertyChangeListener, desde que tenha definida o método propertyChange
resposta: se ele tem um método propertyChange e não tem registo como observador, então não recebe ordens de actualização

o local mais apropriado para colocar código que trata da representação gráfica do semáforo é um método designado propertyChange
resposta: sim, os objetos gráficos são actualizados no propertyChange

o objecto painelDesenho, se tiver uma referência para a classe que deriva de PropertyChangeSupport (modelo), já não precisa de se registar como listener modelo.addProppertyChangeListener(this))
resposta: falso, pode ter uma referência, mas se não tiver um registo como listener/observador, não sabe se existem actualizações, quando os dados se alterarem

a classe que deriva PropertyChangeSupport (a classe observável) deve ter métodos, como passaTempo e desliga, que permitem alterar a informação encapsulada pelo modelo. Nestes métodos, é necessário chamar o método firePropertyChange antes de fazer as alterações ao semáforo
resposta: falso, o firePropertyChange é chamado depois. primeiro mudamos os dados, depois o firePropertyChange vai mandar os observadores fazer a actualização da vista

Tags : ,

Java, várias coisas

ArrayList
Um objecto do tipo ArrayList representa uma sequência ordenada de objectos do tipo T. Implementa o interface List.
A seguinte instrução cria um ArrayList vazio de elementos do tipo Produto:
List produtos= new ArrayList();

Alguns métodos:
public boolean add(E e) acrescenta o elemento e ao fim da lista.
public E remove(int index) remove o elemento da posição index, ajustando os índices seguintes; retorna o elemento removido.
public boolean remove(Object o) remove a primeira ocorrência de o, se existir, ou seja remove o elemento com menor índice tal que (o==null ? get(i)==null : o.equals(get(i))) (se esse elemento existir); retorna true se o elemento foi encontrado e eliminado.
public void clear() remove todos os elementos da lista.
public int size() retorna o numero de elementos da lista.
public int indexOf(Object o) retorna o índica da primeira ocorrência de o na lista, ou -1 se não existir.he element, ou seja, retorna o elemento com menor índice tal que (o==null ? get(i)==null : o.equals(get(i))) ou -1 se este índice não existir.
public E get(int index) retorna o elemento da lista na posição índex.

Percorrer um ArrayList:

for( int i = 0 ; i < produtos.size(); i++){
// …  produtos.get(i)
}

for(Produto produto: produtos){
// …  produto;
} 

Interface Iterator
Um iterator é um objecto que lhe permite percorrer uma colecção. As colecções têm um método:
Iterator iterator();

Que retorna um iterator para a colecção que o invoca.

public interface Iterator<E> {
boolean hasNext();  
// retorna true se existem mais elementos 
E next();          
// retorna o próximo elemento da colecção 
void remove();
}

Interface Set
Um set é uma colecção que não pode ter elementos repetidos. Uma das implementações do interface Set é HashSet.
A seguinte instrução cria um HashSet vazio de elementos do tipo Entidade:
Set< Entidade > c = new HashSet< Entidade >();

Percorrer uma colecção com iterator: Iterator it = v.iterator();

while (it.hasNext()){
// … it.next();
}
}

Para verificar se um determinado objecto pertence a um HashSet, é calculado o hashCode do objecto. O objecto é comparado com equals() só com os elementos do HashSet que têm o mesmo hashCode do objecto que está a ser pesquisado.
O objecto é considerado como pertencente ao HashSet se tiver o mesmo hashCode de um elemento e se também em relação a esse elemento a comparação com equals() der verdadeira.
Os objectos que se colocam num HashSet devem dispor de funções equals() e hashCode() devidamente definidas (se x.equals(y) for true, então x.hashCode() == y.hashCode()).

Ao adicionar um elemento a um HashSet, esta operação só tem sucesso (retornando true e adicionando de facto) se o novo elemento não pertencer ainda ao HashSet.

Interface Map
Um objecto do tipo Map representa uma correspondência chave-valor. Não pode haver chaves repetidas.

public interface Map<K,V> {
V put(K key, V value);    
// insere a correspondência de  (key, value) 
V get(Object key);        
// retorna o valor associado a  key
V remove(Object key);     
// remove a associação cuja chave é  key
boolean containsKey(Object key); 
// contém uma associação com chave  key 
boolean containsValue(Object value); 
// contém uma associação com valor  value int size();
boolean isEmpty();        
// estar vazio
void clear();             
// remove todas as associações
public Set<K> keySet();   
// conjunto das chaves
public Collection<V> values(); 
// colecção dos valores
}

Uma das implementações do interface Map é HashMap.
A seguinte instrução cria um HashMap vazio de elementos do tipo Entidade:

Map map = new HashMap();

Percorrer um map:

Set<String> chaves = map.keySet(); 
Iterator<String> iter = chaves.iterator(); 
while (iter.hasNext()) {
String key = iter.next();
str += " \n" + map.get(key);
}

Interfaces Comparable e Comparator
Implementando o interface Comparable a classe define uma ordem natural entre os seus elementos.

public abstract class Cartao implements Comparable<Cartao>{

protected List<Chamada> chamadas = new ArrayList<Chamada>();
private int numero;
private double saldo;
// …
public int compareTo(Cartao o) {
return numero - o.getNumero();
}
// …
}

public class Telefonica {
private String nome;
private Map<Integer, Cartao> cartoes = new HashMap<Integer, Cartao>();
// …
public String toStringPorNumero(){
List<Cartao> listaOrdenada =
new ArrayList<Cartao>(cartoes.values()); //Faz a cópia
Collections.sort(listaOrdenada);
return "Operadora de telemoveis ***" + nome + "***\n"
+ "Lista ordenada por numero:\n" + listaOrdenada;
}
// …
} 

O interface Comparator permite ordenar a mesma colecção segundo diversos critérios.
É preciso definir um objecto do tipo Comparator, neste caso, um objecto da classe OrdenaPorSaldo que vai ser o segundo argumento da função: Collections.sort(listaOrdenada, new OrdenaPorSaldo());

public class Telefonica {
private String nome;
private Map<Integer, Cartao> cartoes = new HashMap<Integer, Cartao>();
// …
class OrdenaPorSaldo implements Comparator<Cartao> {
public int compare(Cartao o1, Cartao o2) {
if (o1.getSaldo() < o2.getSaldo())
return -1;
else if (o1.getSaldo() > o2.getSaldo())
return 1;
else return 0;
}
}
public String toStringPorSaldo(){ List<Cartao> listaOrdenada =
new ArrayList<Cartao>(cartoes.values()); //Faz a cópia
Collections.sort(listaOrdenada, new OrdenaPorSaldo());
return "Operadora de telemoveis ***" + nome + "***\n"
+ "Lista ordenada por saldo:\n" + listaOrdenada;
}
// …
}
Tags : ,

Java, exercício de análise

assunto: arraylist, equals
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.List;

class Inteiro {

    private int i;

    public Inteiro(int i) {
        this.i = i;
    }

    public void setVal(int i) {
        this.i = i;
    }

    public int getVal() {
        return i;
    }

    public String toString() {
        return "" + i;
    }

    //extra
    public boolean equals(Object ob) {
        if (ob == null) {
            return false;
        }
        if (getClass() != ob.getClass()) {
            return false;
        }
        //se chego aqui já posso comparar o i

        //return (i==ob.i); 
        //dá erro, porque ob não conhece i, então
        
        Inteiro a = (Inteiro) ob;
        //fazemos um cast
        return (i == a.i);
    }
    //e desta forma o System.out.println(i.equals(j));
    //dá true
}

class main {

    public static void main(String[] args) {
        List<Inteiro> listaInteiros = new ArrayList<>();
        //criado um arraylist de listaInteiros

        Inteiro i = new Inteiro(10);
        Inteiro j = new Inteiro(10);

        System.out.println(i == j);
        //saida: falso
        //porque estão em referências diferentes

        System.out.println(i.equals(j));
        //saida: falso
        //o equals faz a comparação que nos programamos lá dentro
        //por exemplo comparar conteudos
        //mas o equals não foi definido, e não dá erro porque
        //está a usar a do object, class Inteiro extends object
        //e a equals no object considera dois objetos iguais
        //se tiverem o mesmo endereço

        listaInteiros.add(i);
        listaInteiros.add(j);

        j = i;
        //j refere o i

        j.setVal(2);
        //o primeiro elemento do array list fica 2

        System.out.println(i);
        //saida: 2

        System.out.println(j);
        //saida: 2

        System.out.println(listaInteiros.get(0));
        //saida: 2

        System.out.println(listaInteiros.get(1));
        //saida: 10
    }
}

Tags : ,

Java, exercício análise

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class UmaExcepcao extends Exception {
    //foi definida uma excepção
}

class Conta {
    int c = 4;

    void f(int i) throws UmaExcepcao {
        if (i < c) {
            System.out.print(" f1");
            f(++i);
            return;
        } else try {
            System.out.print(" f2");
            if (i == c) {
                throw new UmaExcepcao();
            }
        } finally {
            System.out.print(" f3");
        }
        System.out.print(" f4");
    }

    public static void main2(String[] args) {
        Conta c1 = new Conta();
        Conta c2 = new Conta();
        //não existe nenhum construtor

        try {
            c1.f(3);
            // saida: System.out.print(" f1");
            // saida: System.out.print(" f2");
            // i == c, true
            // lança uma excepção, throw new UmaExcepcao(); 
            // saida: faz sempre o finally, System.out.print(" f3");
            // e terminou em estado de excepção e não faz o f4, 
           
            System.out.print(" m1");
            c2.f(4);
            System.out.print(" m2");
            
        } catch (UmaExcepcao ex1) {
            System.out.print(" m3");
            // saida: System.out.print(" m3");
            // porque apanhou uma excepção
            
            try {
                c1.f(5);
                // saida: System.out.print(" f2");
                // i == c, falso
                // saida: System.out.print(" f3");
                // saida: System.out.print(" f4");
                // porque não tinha excepção
                
            } catch (UmaExcepcao ex2) {
                System.out.print(" m4");
            }
        }
        System.out.print(" m5");
        // saida: System.out.print(" m5");
        // porque não tinha excepção
    }
}

//para testar
public class main {
    public static void main(String[] args) {
        Conta.main2(args);
    }
}

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class EstaExcepcao extends Exception {
}

class main {
    static void f() throws EstaExcepcao {
        try {
            System.out.println("Ponto 1");
            throw new EstaExcepcao();
            //saida: ponto 1
            
            //System.out.println("AAAAA"); //se existir dá erro
            //depois do lançamento da excepção dá sempre erro 
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 2");
            //saida: ponto 2
            
            throw e;
            //vai ser relançada
        } finally {
            System.out.println("Ponto 3");
            //saida: ponto 3
        }
         //System.out.println("BBBB"); //se existice
         //como houve erro nunca iria ser executada, por exemplo
         //não havendo o throw
    }

    public static void main(String[] args) {
        try {
            f(); 
            // f() sai em erro, vai fazer o catch
            System.out.println("Ponto 4");
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 5");
            //saida: ponto 5
        } catch (Exception e) {
            System.out.println("Ponto 6");
        }
        System.out.println("Ponto 7");
        //saida: ponto 5
    }
}
Tags : ,

Java, exercício de análise

assunto: map, hashmap
Pergunta:
Pretende-se um programa destinado a modelizar um conjunto de pássaros, especificamente canários e periquitos. Em termos de funcionalidades requeridas, apenas se pretende inserir novas instâncias de pássaros e manter um mapeamento entre os tipos e as respectivas quantidades. Sendo assim, complete o código da Listagem C de modo a que o resultado da sua execução seja: {Piriquito=10, Canario=10}. A classe Passaro encontra-se declarada como abstracta de modo a não poder ser instanciada, não sendo necessário alterá-la. As classes Periquito e Canario requerem a redefinição dos seguintes métodos: String toString(), boolean equals(Object o) e int hashCode().
A interface Map, sendo K o tipo da chave e V o tipo do valor associado, inclui, entre outros, os métodos V put(K k, V v) e V get(Object k). Ambos devolvem o valor associado à chave k fornecida, antes de substituir o valor já existente pelo novo valor v fornecido no caso do put, ou null caso esta não seja encontrada.

package recursopa2;

import java.util.HashMap;
import java.util.Map;

abstract class Passaro {

    public static String PASSARO = "Passaro";
    public static String PERIQUITO = "Periquito";
    public static String CANARIO = "Canario";

    //fabrica de objectos
    public static Passaro criaPassaro(String tipoPassaro) {
        if (tipoPassaro.equalsIgnoreCase(PERIQUITO)) {
            return new Periquito();
        } else if (tipoPassaro.equalsIgnoreCase(CANARIO)) {
            return new Canario();
        } else {
            return null;
        }
    }
}

class Periquito extends Passaro {

    public String toString() {
        return "Periquito";
    }

    public boolean equals(Object ob) {
        //return ob instanceof Periquito;
        //ou em alternativa
        return getClass() == ob.getClass();
    }

    public int hashCode() {
        return PERIQUITO.hashCode();
    }
}

class Canario extends Passaro {

    public String toString() {
        return "Canario";
    }

    public boolean equals(Object ob) {
        return ob instanceof Canario;
    }

    public int hashCode() {
        return CANARIO.hashCode();
    }
}

class MainPassaro {

    public static void adicionaPassaro(Passaro p, Map<Passaro, Integer> gaiola) {
        if (gaiola == null || p == null) {
            return;
        }

        Integer quantidade = gaiola.get(p);
        //se não tive cananrio, a quantidade vem null
        //se já tiver algum, a quantidade vair ser >0

        if (quantidade == null) {
            gaiola.put(p, 1);
            //acrescentamos um elemento novo
        } else {
            gaiola.put(p, quantidade + 1);
            //adiciono um novo, com um update quantidade
        }
    }

    public static void main2(String args[]) {
        //Map</*..f..*/> gaiola = new HashMap<>();
        //resolução:
        Map<Passaro, Integer> gaiola = new HashMap<>();

        Passaro p;

        for (int i = 0; i < 10; i++) {
            adicionaPassaro(Passaro.criaPassaro(Passaro.PERIQUITO), gaiola);
            adicionaPassaro(Passaro.criaPassaro(Passaro.CANARIO), gaiola);
        }
        System.out.println(gaiola);
    }
}

////para testar
public class main {
    public static void main(String[] args) {
        MainPassaro.main2(args);
    }
}
Tags : ,

Java, exercício de análise

assunto: array
pergunta: qual o output do seguinte:

package recursopa2;

class Conta {
    public static int sn = 0;
    public Conta() {
        ++sn;
    }
}

public class main {
    public static void main(String[] args) {
        System.out.print(Conta.sn + " ");
        //saida: 0

        Conta[] a = new Conta[4];
        //com o new Conta[4] é um array de 4 referências nulas para Conta
        //não existe ainda nenhum objecto, não existe nenhum construtor
        
        System.out.print(Conta.sn + " ");
        //saida: 0
        
        for (int i = 0; i < a.length; i++) {
            a[i] = new Conta();
           //aqui já estamos a criar  
        }
        System.out.println(Conta.sn);
        //saida: 4
    }
}
Tags : ,

Programação avançada – capitulo 8 – maquina de estados, exemplo3 (revisitado)

Revisitar o exercício acerca do uso de maquina de estados com a implementação de um jogo de 3×3, onde existem dois jogadores.

A máquina de estados:
é um padrão de programação;
serve para abordar problemas mais complexos;
vai ajudar no fluxo na evolução das aplicações (redirecciona para o estado que vai fazer um determinado processamento);
permite identificar os momentos importantes, na evolução da aplicação/jogo;

Definição dos estados:
está relacionada com a interacção do utilizador;
existem transições entre os estados;
as transições de entrada (métodos) e podem/devem ser condicionados pelo estado do jogo;
as transições de saída (métodos) e podem/devem ser condicionados pelo estado do jogo;
existem então acções do utilizador sobre o jogo, e estas acções resultam em métodos, para haver evolução no jogo;
(identificar as etapas do jogo, que vão ser implementadas, para resolver mini problemas, sub dividir para se simplificar o código que é implementado);

Os estados, são assim:
são representados através de classes;
existe uma classe base, da qual os estados vão derivar (polimorfismo), normalmente do IEstado (através do implements);
e devem ser implementados todos os métodos abstractos que estão definidos no IEstado (usando return para o new “estado”) ou então fica nele próprio (return this).

(2)O IEstado, serve então:
é uma interface, dos estados (e não uma classe);
serve para representar/declarar o que existe, acções possíveis e comuns em todos os estados (através de métodos);
esses métodos são do tipo da interface IEstado;
mas atenção que podem existir algumas acções que podem não ser usadas/implementadas em todos os estados (fica o return this, nas bases), mas têm que ser aqui colocadas, construindo implementações default;
assim sendo os IEstado representam as evoluções (transições) do nosso modelo.

(3)O EstadoAdapter, serve então para:
é uma classe intermédia/genérica que vai implementar os comportamentos default, sem qualquer actualização de estado, para evitar a programação destas acções em estados onde não fazem sentido (normalmente ficam no mesmo estado).
só depois e em cada um dos estados é que os vamos implementar, pois só se justifica no contexto desse estado haver uma evolução na maquina de estados, e é em cada um desses estados que fica implementado
esta classe implementa o IEstado (implements)
implementa todos os métodos abstractos / default (return this), isto é, não existe evolução de estado/fica no mesmo estado.
surge aqui também os testes da evolução, assim estes estados vão ter que ter acesso aos dados do jogo (JogoDados), construtor e get e set
esta classe deve ser public abstract, para não ser instanciada,
e o JogoDados fica protected, evitando fazer uso do método getJogo, e pelas derivadas acedo a esta instância

(4)E agora construir os estados, que são classes derivadas e:
são extends EstadoAdapter
por ser protected a base, esta derivada tem que ter o construtor correspondente (super)
implementar os métodos correspondentes às acções que fazem sentido, são as setas de saída;
os outros não fazem sentido num estado, ficam com o default do EstadoAdapter
os métodos implementados em cada um dos estados fazem então um return new estado, ou this se voltar ao mesmo, sendo que é implementada também a lógica de cada um dos métodos

Surge uma classe
surge então o inicio da máquina de estados, representando numa classe que inicia o primeiro estado por onde arranca (new..), e que vai permitir aceder (get) ou alterar o estado (set)
esta classe vai ter que satisfazer as ordens do utilizador, define os métodos que permitem alterar/mudança de estado (métodos de transição)

Na iteração com o utilizador (texto ou gráfica):
recebe a maquina de estados;
obtém permanente o estado em que se encontra a máquina de estados;
faz uso de instanceof dos estados para invocar a interface que deve surgir ao utilizador.

neste exemplo:
(1)o JogoMaqEstados, gestão/ver a evolução/mudança entre os estados (no diagrama ir de um estado para outro), conhece o estado atual, é a classe de interface entre o IU do utilizador e todas as classes internas (quer aquelas que representam os estados, quer os dados, que representam o jogo (tem assim informação sobre o jogo (JogoDados), e o estado em que estamos (IEstado));
o JogoMaqEstados tem ainda a interface para todos os outros estados, onde actualiza a situação do estado;
os estados, recebem a entidade jogo, como referência;
já a grelha, onde estão as peças, o jogador, este tipo de dados ficam em JogoDados;
JogoDados, representa assim o tabuleiro do jogo, onde se fazem todas as verificações;
Jogador, representada cada um dos jogos;
Peca, as peças do tabuleiro de jogo;
IEstado;
EstadoAdapter

(10) A interface (IU) também precisa de ir buscar coisas ao jogo, mas quem trata disso é o JogoMaqEstados

package me_jogopecasr;

import me_jogopecasr.iu.texto.IUtexto;
import me_jogopecasr.logica.JogoMaqEstados;

public class Me_jogoPecasR {

    public static void main(String[] args) {

        IUtexto iuTexto = new IUtexto(new JogoMaqEstados());
        iuTexto.corre();
    }
}
package me_jogopecasr.iu.texto;

import java.util.Scanner;
import me_jogopecasr.logica.JogoMaqEstados;
import me_jogopecasr.logica.estados.AguardaColocacao;
import me_jogopecasr.logica.estados.AguardaDevolucao;
import me_jogopecasr.logica.estados.AguardaInicio;
import me_jogopecasr.logica.estados.IEstado;

public class IUtexto {

    private JogoMaqEstados jogo;
    private boolean sair = false;

    public IUtexto(JogoMaqEstados jogo) {
       this.jogo = jogo;
    }

    void iuAguardaInicio() {

        if ((jogo.getJogador1() != null && jogo.getJogador1().isGanhou())) {
            System.out.println("\n" + jogo.getJogador1() + "\n" + jogo.grelhaToString());
        } else if (jogo.getJogador2() != null && jogo.getJogador2().isGanhou()) {
            System.out.println("\n" + jogo.getJogador2() + "\n" + jogo.grelhaToString());
        }
        System.out.println("\n=== AGUARDA INICIO ===\n"
                + (jogo.getJogador1() != null ? "" + jogo.getJogador1() : "")
                + (jogo.getJogador2() != null ? "" + jogo.getJogador2() : ""));
        while (true) {
            System.out.println("\n0 - Sair\n1 - Define nome de jogador\n2 - Comecar jogo");
            char c = ' ';
            Scanner sc = new Scanner(System.in);
            c = sc.next().charAt(0);
            if ((c == '0')) {
                sair = true;
                return;
            }
            if ((c == '1')) { //1 - Define nome de jogador
                System.out.println("Numero (1 ou 2)  e nome do jogador: ");
                while (!sc.hasNextInt());
                int num = sc.nextInt();
                System.out.println(" numero: " + num);
                String nome = sc.next();
                jogo.defineNomeJogador(num, nome);
                System.out.println(" nome: " + nome);
                return;
            }
            if ((c == '2')) { //2 - Comecar jogo
                System.out.println("Comecar jogo: ");
                jogo.comecarJogo();
                return;
            }
        }
    }

    void iuAguardaColocacao() {
        System.out.println("\n=== AGUARDA COLOCACAO === \n"
                + jogo.getJogador1()
                + jogo.getJogador2()
                + "\nJogador activo: " + jogo.getNomeJogadorActivo()
                + "\n" + jogo.grelhaToString());

        System.out.println("\n1 - Jogar : linha  coluna\n2 - Abandonar");
        char c = ' ';
        Scanner sc = new Scanner(System.in);
        c = sc.next().charAt(0);
        if ((c == '1')) {

            System.out.print(jogo.getNomeJogadorActivo() + ">");

            while (!sc.hasNextInt());
            int linha = sc.nextInt();

            while (!sc.hasNextInt());
            int coluna = sc.nextInt();
            jogo.jogar(jogo.getNumJogadorActivo(), linha, coluna);
        }
        if ((c == '2')) {
            jogo.abandonar(jogo.getNumJogadorActivo());
            return;
        }
   
    }

    void iuAguardaDevolucao() {
        System.out.println("\n=== AGUARDA DEVOLUCAO === \n"
                + jogo.getJogador1()
                + jogo.getJogador2()
                + "\nJogador activo: " + jogo.getNomeJogadorActivo()
                + "\n" + jogo.grelhaToString());

//        System.out.println("\nDevolver : linha  coluna\nAbandonar: -1");
         System.out.println("\n1 - Devolver : linha  coluna\n2 - Abandonar");
        char c = ' ';
        Scanner sc = new Scanner(System.in);
        c = sc.next().charAt(0);
        if ((c == '1')) {
        System.out.print(jogo.getNomeJogadorActivo() + ">");
        while (!sc.hasNextInt());
        int linha = sc.nextInt();
 
        while (!sc.hasNextInt());
        int coluna = sc.nextInt();
        jogo.devolver(jogo.getNumJogadorActivo(), linha, coluna);
        }
        if ((c == '2')) {
            jogo.abandonar(jogo.getNumJogadorActivo());
            return;
        }
   
    }

    public void corre() {

        while (!sair) {
            IEstado estado = jogo.getEstado();
            if (estado instanceof AguardaInicio) {
                iuAguardaInicio();
            } else if (estado instanceof AguardaColocacao) {
                iuAguardaColocacao();
            } else if (estado instanceof AguardaDevolucao) {
                iuAguardaDevolucao();
            }
        }

    }
}
package me_jogopecasr.logica;

public interface Constantes {
    int DIM = 3;
}
package me_jogopecasr.logica;

import java.util.ArrayList;
import java.util.List;


public class Jogador implements Constantes {

    private JogoDados jogo;
    private String nome;
    private List<Peca> mao = new ArrayList<Peca>();
    private boolean ganhou;

    public Jogador(String nome, JogoDados j) {
        this.nome = nome;
        this.jogo = j;
        ganhou = false;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getNome() {
        return nome;
    }

    public boolean isGanhou() {
        return ganhou;
    }

    public void setGanhou(boolean ganhou) {
        this.ganhou = ganhou;
    }

    public void recebePecas() {
        mao.clear();
        for (int i = 0; i < DIM; i++) {
            mao.add(new Peca(this));
        }
        ganhou = false;
    }
     public void recebePeca(Peca peca) {
            mao.add(peca);   
    }

    public boolean temPecas() {
        return mao.size() > 0;
    }

    public boolean jogar(int linha, int coluna) {
        if (mao.size() == 0) {
            return false;
        }
        Peca peca = mao.get(0);
        if (jogo.setPeca(peca, linha, coluna)) {
            // jogou
            mao.remove(0);
            if (jogo.ganhou(this)) {
                ganhou = true;
            }
            return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return "Jogador " + nome + " mao=" + mao + (ganhou ? " == GANHOU ==" : "") + "\n";
    }

    public int getNumPecas() {
        return mao.size();
    }
}
package me_jogopecasr.logica;

import java.util.ArrayList;
import java.util.List;

public class JogoDados implements Constantes{
 
    private List<Jogador> jogadores = new ArrayList<Jogador>();

    private int numJogActivo;
    private Peca[][] grelha;
    

    public JogoDados() {
        
        jogadores.add(new Jogador("A", this));
        jogadores.add(new Jogador("B", this));
        grelha = new Peca[DIM][DIM];
    }

    public Jogador getJogadorActivo() {
        return jogadores.get(numJogActivo - 1);
    }
    public String getNomeJogadorActivo() {
        return jogadores.get(numJogActivo - 1).getNome();
    }

    public Jogador getJogadorNaoActivo() {
        if (numJogActivo == 1) {
            return jogadores.get(1);
        } else if (numJogActivo == 2) {
            return jogadores.get(0);
        }
        return null;
    }

    public int getNumJogadorActivo() {
        return numJogActivo;
    }

    public int getNumJogadorNaoActivo() {
        return (numJogActivo == 1? 1: 2);
    }

    public Jogador getJogador1() {
        return jogadores.get(0);
    }

    public Jogador getJogador2() {
        return jogadores.get(1);
    }

    


    public Peca getPeca(int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return null;
        }
        if (grelha == null) {
            return null;
        }
        return grelha[linha][coluna];
    }

    public boolean setPeca(Peca peca, int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }
        if (grelha[linha][coluna] != null) {
            return false;
        }
        grelha[linha][coluna] = peca;
        return true;
    }

    public boolean retiraPeca(int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }
        if (grelha[linha][coluna] == null) {
            return false;
        }
        grelha[linha][coluna] = null;
        return true;
    }

    public void jogaOutro() {
        numJogActivo = numJogActivo == 1 ? 2 : 1;
    }

  
    public boolean inicializa() {

        grelha = new Peca[DIM][DIM];
        jogadores.get(0).recebePecas();
        jogadores.get(1).recebePecas();

        numJogActivo = 1;

        return true;
    }

    public boolean setNomeJogador(int num, String nome) {
        try{
            jogadores.get(num-1).setNome(nome);
            return true;
        }catch(IndexOutOfBoundsException e){
            return false;
        }
    }

    private boolean isEmDiagonalPrincipal(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (grelha[i][i] == null || grelha[i][i].getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmDiagonalSecundaria(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (grelha[i][DIM - 1 - i] == null || grelha[i][DIM - 1 - i].getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmDiagonal(Jogador jogador) {
        return isEmDiagonalPrincipal(jogador) || isEmDiagonalSecundaria(jogador);
    }

    private boolean isEmHorizontal(Jogador jogador, int linha) {
        for (Peca peca : grelha[linha]) {
            if (peca == null || peca.getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmVertical(Jogador jogador, int coluna) {
        for (int i = 0; i < grelha[coluna].length; i++) {
            Peca peca = grelha[i][coluna];
            if (peca == null || peca.getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmHorizontal(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (isEmHorizontal(jogador, i)) {
                return true;
            }
        }
        return false;
    }

    private boolean isEmVertical(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (isEmVertical(jogador, i)) {
                return true;
            }
        }
        return false;
    }

    public boolean ganhou(Jogador jogador) {

        return isEmHorizontal(jogador) || isEmDiagonal(jogador) || isEmVertical(jogador);
    }

      public boolean jogar(int numeroJogador, int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }
        if(numJogActivo != numeroJogador){
            return false;
        }
      
        Jogador j = getJogadorActivo();
        
        
        if(!j.jogar(linha, coluna)){
            return false;
        }
        return true;
    }
    
      public boolean devolver(int numeroJogador, int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }
        
        if(numJogActivo != numeroJogador){
            return false;
        }
       Peca peca = getPeca(linha, coluna);
        Jogador j = getJogadorActivo();
         if (peca == null || peca.getJogador() != j) {
            return false;
        }
        
        if(!retiraPeca(linha, coluna)){
            return false;
        }
        j.recebePeca(peca);
        return true;
    }
    
    public String grelhaToString() {
        String s = "";
        for (int i = 0; i < DIM; i++) {
            for (int j = 0; j < DIM; j++) {
                String casa;
                if (grelha[i][j] != null) {
                    casa = "" + grelha[i][j].getJogador().getNome().charAt(0);
                } else {
                    casa = " ";
                }
                s += "|\t" + casa + "\t";
            }
            s += "|\n";
        }
        return s;
    }

   
    public boolean acabou() {
        return ganhou(jogadores.get(0)) || ganhou(jogadores.get(1));

    }
    
}

package me_jogopecasr.logica;

import me_jogopecasr.logica.estados.AguardaInicio;
import me_jogopecasr.logica.estados.IEstado;

public class JogoMaqEstados {
    JogoDados jogo;
    IEstado estado;

    public JogoMaqEstados() {
        //1)
        this.jogo = new JogoDados();
        //7
        this.estado = new AguardaInicio(jogo);
    }

    public JogoDados getJogo() {
        return jogo;
    }

    public void setJogo(JogoDados jogo) {
        this.jogo = jogo;
    }

    public IEstado getEstado() {
        return estado;
    }

    public void setEstado(IEstado estado) {
        this.estado = estado;
    }

    //8 redirecionar, agulhar, as acções para os estados, o interface para todas as outras classes
    public void defineNomeJogador(int numeroJogador, String nome) {
        //8.1 a evolução do estado, retorna o estado seguinte
        estado = estado.defineNomeJogador(numeroJogador, nome); //ou usar o setEstado
    }

    public void comecarJogo() { //no infitivo
        estado = estado.comecaJogo();
    }

    public void jogar(int numeroJogador, int linha, int coluna) {
        estado = estado.joga(numeroJogador, linha, coluna);
    }

    public void devolver(int numeroJogador, int linha, int coluna) {
        estado = estado.devolve(numeroJogador, linha, coluna);
    }

    public void abandonar(int numeroJogador) {
        estado = estado.abandona(numeroJogador);
    }

    //9 redirencuionar para o modelo de dados
    public Jogador getJogador1() {
        return jogo.getJogador1();
    }

    public Jogador getJogador2() {
        return jogo.getJogador2();
    }

    //11 redirencuionar para o modelo de dados
    public String getNomeJogadorActivo() {
        return jogo.getNomeJogadorActivo();
    }

    public String grelhaToString() {
        return jogo.grelhaToString();
    }

    public int getNumJogadorActivo() {
        return jogo.getNumJogadorActivo();
    }

}

package me_jogopecasr.logica;

public class Peca {
    private Jogador jogador;

    public Peca(Jogador jogador) {
        this.jogador = jogador;
    }

    public Jogador getJogador() {
        return jogador;
    }

    public String toString(){
        return "" + jogador.getNome().charAt(0);
    }
}

package me_jogopecasr.logica.estados;

import me_jogopecasr.logica.JogoDados;
//5
public class AguardaColocacao extends EstadoAdapter{
    //6.2.3 ver se ele não colocou no mesmo local
    int l, c; 
    
    //5.1
    public AguardaColocacao(JogoDados jogo) {
        super(jogo);
        //6.2.5
        l = c-1;
    }
    //6.2.4
        public AguardaColocacao(JogoDados jogo, int l, int c) {
        super(jogo);
        this.l = l;
        this.c = c;
    }

    //5.2
    @Override
    public IEstado abandona(int numeroJogador) {
        //poderia ver qual é o jogador e atribuir a vitória ao outro
        return new AguardaInicio(jogo);
    }
    
    //5.3
    @Override
    public IEstado joga(int numeroJogador, int linha, int coluna) {
         //6.2.6, testar se é a mesma jogada
         if(linha == l && coluna == c){
             return this;
         }
        
        
        //5.3.1, vamos realizar o jogar
        if(!jogo.jogar(numeroJogador, linha, coluna)){
            return this;
        }
        
        //5.3.2, ver se ele ganhou
        if(jogo.getJogadorActivo().isGanhou()){
            return new AguardaInicio(jogo);
        }
        //5.3.3, mudar de jogador
        jogo.jogaOutro();
        
        //5.3.4, ver se tem peças 
         if(jogo.getJogadorActivo().isGanhou()){
            return new AguardaColocacao(jogo); //ou return this, fica no mesmo estado, e com l e c a -1
        }
         
         
         //5.3.5, 
         return new AguardaDevolucao(jogo);
    }
    
    
    
}


package me_jogopecasr.logica.estados;

import me_jogopecasr.logica.JogoDados;

//6
public class AguardaDevolucao extends EstadoAdapter {

    public AguardaDevolucao(JogoDados jogo) {
        super(jogo);
    }

    //6.1
    @Override
    public IEstado abandona(int numeroJogador) {
        return new AguardaInicio(jogo);
    }
    
    //6.2
    @Override
    public IEstado devolve(int numeroJogador, int linha, int coluna) {
        //6.2.1 adcionar a devolção
        if(jogo.devolver(numeroJogador, linha, coluna)){
            //o devolver já verifica
            return new AguardaColocacao(jogo, linha, coluna);  //6.2.7
        }
        //6.2.2 fica no mesmo estado
        return this;
    }
    
    
}

package me_jogopecasr.logica.estados;

import me_jogopecasr.logica.JogoDados;

public class AguardaInicio extends EstadoAdapter{
    //4) por ser protected a base, esta derivada tem que ter um construtor correspondente
    public AguardaInicio(JogoDados jogo) {
        super(jogo);
    }
    
    //4.2) implementar os métodos correspondentes às acções que fazem sentido, são as setas de saída

    @Override
    public IEstado defineNomeJogador(int numeroJogador, String nome) {
        //4.4
        jogo.setNomeJogador(numeroJogador, nome);
        //4.3
        return this;
    }

    @Override
    public IEstado comecaJogo() {
        //4.4 testes para começar um jogo
        if(jogo.getJogador1()== null || jogo.getJogador2() ==null){
        //fico no mesmo estado
        return this;
        }
        
        //12
        jogo.inicializa();
        return new AguardaColocacao(jogo);
    }
    
    
}

package me_jogopecasr.logica.estados;

    //3) existem acções que não fazem sent
import me_jogopecasr.logica.JogoDados;

public abstract class EstadoAdapter implements IEstado{
    //3.2) acesso aos jogos de dados
    //3.3) protected, evitando fazer uso do método getJogo, e pelas derivadas acedo a esta instancia
    protected JogoDados jogo;

    public EstadoAdapter(JogoDados jogo) {
        this.jogo = jogo;
    }

    public JogoDados getJogo() {
        return jogo;
    }

    public void setJogo(JogoDados jogo) {
        this.jogo = jogo;
    }
    
    
    //3.1)
    @Override
    public IEstado defineNomeJogador(int numeroJogador, String nome) {
        return this;
    }

    @Override
    public IEstado comecaJogo() {
        return this;
    }

    @Override
    public IEstado joga(int numeroJogador, int linha, int coluna) {
        return this;
    }

    @Override
    public IEstado devolve(int numeroJogador, int linha, int coluna) {
        return this;
    }

    @Override
    public IEstado abandona(int numeroJogador) {
        return this;
    }
    
}

package me_jogopecasr.logica.estados;

//2) definir todos os estados
public interface IEstado {
    IEstado defineNomeJogador(int numeroJogador, String nome);
    IEstado comecaJogo();
    IEstado joga(int numeroJogador, int linha, int coluna);
    IEstado devolve(int numeroJogador, int linha, int coluna);
    IEstado abandona(int numeroJogador);
}
Tags : , , ,

Programação avançada – capitulo 8 – maquina de estados, exemplo3

Exemplo de uma maquina de estado, usando como referência a implementação de um jogo de 3×3, onde existem dois jogadores.
O diagrama da maquina de estados dado:

Outra versão do diagrama da maquina de estados:

Em que ficou:

Com:

package me_jogopecas;

import me_jogopecas.iu.texto.IUTexto;
import me_jogopecas.logica.estados.JogoMaquinaEstados;

public class Me_jogoPecas {

    public static void main(String[] args) {
           IUTexto iuTexto = new IUTexto(new JogoMaquinaEstados());
           iuTexto.corre();
    }
    
}
package me_jogopecas.iu.texto;

import java.util.Scanner;
import me_jogopecas.logica.estados.*;

public class IUTexto {

    private JogoMaquinaEstados jogo;
    private boolean sair = false;

    public IUTexto(JogoMaquinaEstados jogo) {
        this.jogo = jogo;
    }

    void iuAguardaInicio() {

        if ((jogo.getJogador1() != null && jogo.getJogador1().isGanhou())) {
            System.out.println("\n" + jogo.getJogador1() + "\n" + jogo.grelhaToString());
        } else if (jogo.getJogador2() != null && jogo.getJogador2().isGanhou()) {
            System.out.println("\n" + jogo.getJogador2() + "\n" + jogo.grelhaToString());
        }
        System.out.println("\n=== AGUARDA INICIO ===\n"
                + (jogo.getJogador1() != null ? "" + jogo.getJogador1() : "")
                + (jogo.getJogador2() != null ? "" + jogo.getJogador2() : ""));
        while (true) {
            System.out.println("\n0 - Sair\n1 - Define nome de jogador\n2 - Comecar jogo\n3 - Ler jogo");
            char c = ' ';
            Scanner sc = new Scanner(System.in);
            c = sc.next().charAt(0);
            if ((c == '0')) {
                sair = true;
                return;
            }
            if ((c == '1')) { //1 - Define nome de jogador
                System.out.println("Numero (1 ou 2)  e nome do jogador: ");
                while (!sc.hasNextInt());
                int num = sc.nextInt();
                System.out.println(" numero: " + num);
                String nome = sc.next();
                jogo.defineNomeJogador(num, nome);
                System.out.println(" nome: " + nome);
                return;
            }
            if ((c == '2')) { //2 - Comecar jogo
                System.out.println("Comecar jogo: ");
                jogo.comecarJogo();
                return;
            }
            if ((c == '3')) { //3 - Ler o jogo
                System.out.println("Ler o  jogo: ");
                String ficheiroLer = sc.next();
               // jogo.ler(ficheiroLer);
                return;
            }
        }
    }

    void iuAguardaColocacao() {
        System.out.println("\n=== AGUARDA COLOCACAO === \n"
                + jogo.getJogador1()
                + jogo.getJogador2()
                + "\nJogador activo: " + jogo.getNomeJogadorActivo()
                + "\n" + jogo.grelhaToString());

        System.out.println("\n1 - Jogar : linha  coluna\n2 - Abandonar");
        char c = ' ';
        Scanner sc = new Scanner(System.in);
        c = sc.next().charAt(0);
        if ((c == '1')) {

            System.out.print(jogo.getNomeJogadorActivo() + ">");

            while (!sc.hasNextInt());
            int linha = sc.nextInt();

            while (!sc.hasNextInt());
            int coluna = sc.nextInt();
            jogo.jogar(jogo.getNumJogadorActivo(), linha, coluna);
        }
        if ((c == '2')) {
            System.out.println("Guardar o  jogo: ");
            String ficheiroGuardar = sc.next();
           // jogo.grava(ficheiroGuardar);
            jogo.abandonar(jogo.getNumJogadorActivo());
            return;
        }
    }

    void iuAguardaDevolucao() {
        System.out.println("\n=== AGUARDA DEVOLUCAO === \n"
                + jogo.getJogador1()
                + jogo.getJogador2()
                + "\nJogador activo: " + jogo.getNomeJogadorActivo()
                + "\n" + jogo.grelhaToString());

//        System.out.println("\nDevolver : linha  coluna\nAbandonar: -1");
        System.out.println("\n1 - Devolver : linha  coluna\n2 - Abandonar");
        char c = ' ';
        Scanner sc = new Scanner(System.in);
        c = sc.next().charAt(0);
        if ((c == '1')) {
            System.out.print(jogo.getNomeJogadorActivo() + ">");
            while (!sc.hasNextInt());
            int linha = sc.nextInt();

            while (!sc.hasNextInt());
            int coluna = sc.nextInt();
            jogo.devolver(jogo.getNumJogadorActivo(), linha, coluna);
        }
        if ((c == '2')) {
            jogo.abandonar(jogo.getNumJogadorActivo());
            return;
        }
    }

    public void corre() {

        while (!sair) {
            IEstado estado = jogo.getEstado();
            if (estado instanceof AguardaInicio) {
                iuAguardaInicio();
            } else if (estado instanceof AguardaColocacao) {
                iuAguardaColocacao();
            } else if (estado instanceof AguardaDevolucao) {
                iuAguardaDevolucao();
            }
        }

    }
}
package me_jogopecas.logica;

public interface Constantes {
    int DIM  =3;
}
package me_jogopecas.logica;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import static me_jogopecas.logica.Constantes.*;

public class Jogador implements Constantes, Serializable{

    private String nome;
    private JogoDados jogo;
    
    //lista de peças no inicio
    private List<Peca> mao = new ArrayList<Peca>(); 
    
    private boolean ganhou;

    public Jogador(String nome, JogoDados j) {
        this.nome = nome;
        this.jogo = j;
        ganhou = false;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public JogoDados getJogo() {
        return jogo;
    }

    public void setJogo(JogoDados jogo) {
        this.jogo = jogo;
    }

    public List<Peca> getMao() {
        return mao;
    }

    public void setMao(List<Peca> mao) {
        this.mao = mao;
    }

    public boolean isGanhou() {
        return ganhou;
    }

    public void setGanhou(boolean ganhou) {
        this.ganhou = ganhou;
    }

    //quando começar o jogo!
    public void recebePecas() {
        mao.clear();
        for (int i = 0; i < DIM; i++) { mao.add(new Peca(this)); } ganhou = false; } public int getNumPecas(){ return mao.size(); } //quando a peça é devolvida public void recebePeca(Peca peca) { mao.add(new Peca(this)); } public boolean temPecas() { return mao.size() > 0;
    }
    
    public boolean jogar(int linha, int coluna){
        if(mao.size()==0){
            return false;
        }
        //as peças são todas iguais
        Peca peca = mao.get(0);
        if(jogo.setPeca(peca, linha, coluna)){
            //jogou
            mao.remove(0);
            if(jogo.ganhou(this)){
                ganhou = true;
            }
            return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return "Jogador " + nome + " mao=" + mao + (ganhou ? " == GANHOU ==" : "") + "\n" ;
    }   
}
package me_jogopecas.logica;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class JogoDados implements Constantes, Serializable  {

    private List<Jogador> jogadores = new ArrayList<Jogador>();

    private int numJoActivo;
    private Peca[][] grelha;

    public JogoDados() {
        jogadores.add(new Jogador("A", this));
        jogadores.add(new Jogador("B", this));
        grelha = new Peca[DIM][DIM];
    }

    public Jogador getJogadorActivo() {
        //considera-se que o jogador activo é 1 ou 2, daí o -1
        return jogadores.get(numJoActivo - 1);
    }

    public String getNomeJogadorActivo() {
        return jogadores.get(numJoActivo - 1).getNome();
    }

    public Jogador getJogadorNaoActivo() {
        if (numJoActivo == 1) {
            return jogadores.get(1);
        } else if (numJoActivo == 2) {
            return jogadores.get(0);
        }
        return null;
    }

    public int getNumJogadorActivo() {
        return numJoActivo;
    }

    public int getNumJogadorNaoActivo() {
        return (numJoActivo == 1 ? 1 : 2);
    }

    public Jogador getJogador1() {
        return jogadores.get(0);
    }

    public Jogador getJogador2() {
        return jogadores.get(1);
    }

    public Peca getPeca(int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return null;
        }
        if (grelha == null) {
            return null;
        }
        return grelha[linha][coluna];
    }

    public boolean setPeca(Peca peca, int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }
        if (grelha[linha][coluna] != null) {
            return false;
        }
        grelha[linha][coluna] = peca;
        return true;
    }

    public boolean retiraPeca(int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }
        if (grelha[linha][coluna] == null) {
            return false;
        }
        grelha[linha][coluna] = null;
        return true;
    }

    public void jogaOutro() {
        numJoActivo = numJoActivo == 1 ? 2 : 1;
    }

    public boolean inicializa() {

        grelha = new Peca[DIM][DIM];
        jogadores.get(0).recebePecas();
        jogadores.get(1).recebePecas();

        numJoActivo = 1;

        return true;
    }

    public boolean setNomeJogador(int num, String nome) {
        //falta validar se o num é válido
        try {
            //tento aceder a um elemento do array que nao existe
            jogadores.get(num - 1).setNome(nome);
            return true;
        } catch (IndexOutOfBoundsException e) {
            return false;
        }
    }

    private boolean isEmDiagonalPrincipal(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (grelha[i][i] == null || grelha[i][i].getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmDiagonalSecundaria(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (grelha[i][DIM - 1 - i] == null || grelha[i][DIM - 1 - i].getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmDiagonal(Jogador jogador) {
        return isEmDiagonalPrincipal(jogador) || isEmDiagonalSecundaria(jogador);
    }

    private boolean isEmHorizontal(Jogador jogador, int linha) {
        for (Peca peca : grelha[linha]) {
            if (peca == null || peca.getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmVertical(Jogador jogador, int coluna) {
        for (int i = 0; i < grelha[coluna].length; i++) {
            Peca peca = grelha[i][coluna];
            if (peca == null || peca.getJogador() != jogador) {
                return false;
            }
        }
        return true;
    }

    private boolean isEmHorizontal(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (isEmHorizontal(jogador, i)) {
                return true;
            }
        }
        return false;
    }

    private boolean isEmVertical(Jogador jogador) {
        for (int i = 0; i < DIM; i++) {
            if (isEmVertical(jogador, i)) {
                return true;
            }
        }
        return false;
    }

    public boolean ganhou(Jogador jogador) {
        return isEmHorizontal(jogador) || isEmDiagonal(jogador) || isEmVertical(jogador);
    }

    public boolean jogar(int numeroJogador, int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }
        if (numJoActivo != numeroJogador) {
            return false;
        }

        Jogador j = getJogadorActivo();

        if (!j.jogar(linha, coluna)) {
            return false;
        }
        return true;
    }

    public boolean devolver(int numeroJogador, int linha, int coluna) {
        if (linha < 0 || linha >= DIM || coluna < 0 || coluna >= DIM) {
            return false;
        }

        if (numJoActivo != numeroJogador) {
            return false;
        }
        Peca peca = getPeca(linha, coluna);
        Jogador j = getJogadorActivo();
        if (peca == null || peca.getJogador() != j) {
            return false;
        }

        if (!retiraPeca(linha, coluna)) {
            return false;
        }
        j.recebePeca(peca);
        return true;
    }

    public String grelhaToString() {
        String s = "";
        for (int i = 0; i < DIM; i++) {
            for (int j = 0; j < DIM; j++) {
                String casa;
                if (grelha[i][j] != null) {
                    casa = "" + grelha[i][j].getJogador().getNome().charAt(0);
                } else {
                    casa = " ";
                }
                s += "|\t" + casa + "\t";
            }
            s += "|\n";
        }
        return s;
    }

    public boolean acabou() {
        return ganhou(jogadores.get(0)) || ganhou(jogadores.get(1));
    }
}
package me_jogopecas.logica;

import java.io.Serializable;

public class Peca implements Serializable {
    private Jogador jogador;

    public Peca(Jogador jgd) {
        this.jogador = jgd;
    }

    public Jogador getJogador() {
        return jogador;
    }

    public void setJogador(Jogador jogador) {
        this.jogador = jogador;
    }

    @Override
    public String toString() {
        return "" + jogador.getNome().charAt(0);
    }
}
package me_jogopecas.logica.estados;

import me_jogopecas.logica.JogoDados;

public class AguardaColocacao extends EstadoAdapter {

    //para informação adicional
    int l, c;

    public AguardaColocacao(JogoDados jogodados) {
        super(jogodados);
        //para informação adicional
        l = c = -1; //se vier return this
    }

    //para informação adicional
    public AguardaColocacao(JogoDados jogo, int l, int c) {
        super(jogo);
        this.l = l;
        this.c = c;
    }

    //setas de saida
    @Override
    public IEstado abandona(int numeroJogador) {
        //podiamos atribuir a vitoria a um jogador, olhando para numeroJogador

        //voltamos ao inicio
        return new AguardaInicio(jogodados);
    }

    @Override
    public IEstado joga(int numeroJogador, int linha, int coluna) {
        //informação adicional
        if (linha == l && coluna == c) {
            return this;
        }

        //jogar normal, o jogar faz o teste se pode ou nao jogar
        jogodados.jogar(numeroJogador, linha, coluna);
        //verificar se o jogador activo
        if (jogodados.getJogadorActivo().isGanhou()) {
            return new AguardaInicio(jogodados);
        }
        jogodados.jogaOutro();
        //jogar a um jogador que não tem peças
        //jogar que nao tem pecas
        if (jogodados.getJogadorActivo().temPecas()) {
            //return this; //tb funciona
            //para informação adicional
            return new AguardaColocacao(jogodados);
        }
        return new AguardaDevolucao(jogodados);
    }
}
package me_jogopecas.logica.estados;

import me_jogopecas.logica.JogoDados;

public class AguardaDevolucao extends EstadoAdapter {

    public AguardaDevolucao(JogoDados jogodados) {
        super(jogodados);
    }

    @Override
    public IEstado abandona(int numeroJogador) {
        return new AguardaInicio(jogodados);
    }

    @Override
    public IEstado devolve(int numeroJogador, int linha, int coluna) {
        if (jogodados.devolver(numeroJogador, linha, coluna)) {
            //return new AguardaColocacao(jogodados);
            //informação adicional
            return new AguardaColocacao(jogodados, linha, coluna);
        }
        return this;
    }
}
package me_jogopecas.logica.estados;

import me_jogopecas.logica.JogoDados;

public class AguardaInicio extends EstadoAdapter {

    //construtor que redireciona para a classe base
    public AguardaInicio(JogoDados jogodados) {
        super(jogodados);
    }

    //setas de saida, os outros não fazem sentido
    @Override
    public IEstado defineNomeJogador(int numeroJogador, String nome) {
        //qual o novo estado depois de defineNomeJogador
        //agora vou atuar sobre o jogo
        jogodados.setNomeJogador(numeroJogador, nome);

        return this; //fico no mesmo estado
    }

    @Override
    public IEstado comecaJogo() {
        //testes para verificar se já tinhamos os dois jogadores
        if(jogodados.getJogador1()==null || jogodados.getJogador2()==null){
            return this;
        }
        jogodados.inicializa();
        return new AguardaColocacao(jogodados);
    }

}

package me_jogopecas.logica.estados;

import java.io.Serializable;
import me_jogopecas.logica.JogoDados;

//abstract para nao ser instanciada 
public abstract class EstadoAdapter implements IEstado, Serializable{
    
    
    JogoDados jogodados;//tem que ter acesso aos dados de jogo

    //podemos colocar como protected, para ser usado apenas nas classes derivadas
    public EstadoAdapter(JogoDados jogod) {
        this.jogodados = jogod;
    }

    public JogoDados getJogodados() {
        return jogodados;
    }

    public void setJogodados(JogoDados jogodados) {
        this.jogodados = jogodados;
    }

    @Override
    public IEstado defineNomeJogador(int numeroJogador, String nome) {
       return this;
    }

    @Override
    public IEstado comecaJogo() {
       return this;
    }

    @Override
    public IEstado joga(int numeroJogador, int linha, int coluna) {
        return this;
    }

    @Override
    public IEstado devolve(int numeroJogador, int linha, int coluna) {
        return this;
    }

    @Override
    public IEstado abandona(int numeroJogador) {
        return this;
    }
    //o interface precisa de ir buscar coisas para as mostrar
    
}

package me_jogopecas.logica.estados;

public interface IEstado {
    //definir todas as acções o jogo
    IEstado defineNomeJogador(int numeroJogador, String nome);
    IEstado comecaJogo();
    IEstado joga(int numeroJogador, int linha, int coluna);
    IEstado devolve(int numeroJogador, int linha, int coluna);
    IEstado abandona(int numeroJogador);
}

package me_jogopecas.logica.estados;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import me_jogopecas.logica.Jogador;
import me_jogopecas.logica.JogoDados;

public class JogoMaquinaEstados implements Serializable {

    //se JogoMaquinaEstados é Serializable as classes de base tb têm que ser
    JogoDados jogodados;
    IEstado estado;

    public JogoMaquinaEstados() {
        //criar o meu jogo
        this.jogodados = new JogoDados();
        //desenvolver, evoluir, programação dos estados (do diagrama)
        this.estado = new AguardaInicio(jogodados);
    }

    public IEstado getEstado() {
        return estado;
    }

    public void setEstado(IEstado estado) {
        this.estado = estado;
    }

    //implementar todos os estados, através desta maquina de estados
    //interface de todas as classes
    public void defineNomeJogador(int numeroJogador, String nome) {
        //estado seguinte vai ser do retornar..
        estado = estado.defineNomeJogador(numeroJogador, nome);
    }

    public void comecarJogo() {
        estado = estado.comecaJogo();
    }

    public void jogar(int numeroJogador, int linha, int coluna) {
        estado = estado.joga(numeroJogador, linha, coluna);
    }

    public void devolver(int numeroJogador, int linha, int coluna) {
        estado = estado.devolve(numeroJogador, linha, coluna);
    }

    public void abandonar(int numeroJogador) {
        estado = estado.abandona(numeroJogador);
    }

    //os métodos que surgem no IUTexto
    public Jogador getJogador1() {
        return jogodados.getJogador1();
    }

    public Jogador getJogador2() {
        return jogodados.getJogador2();
    }

    public String getNomeJogadorActivo() {
        return jogodados.getNomeJogadorActivo();
    }

    public int getNumJogadorActivo() {
        return jogodados.getNumJogadorActivo();
    }

    public String grelhaToString() {
        return jogodados.grelhaToString();
    }

    //ou em alternativa dava acesso ao jogodados
    public JogoDados getJogo() {
        return jogodados;
    }

    //gravação dos ficheiros
    public void grava(String filename) throws IOException {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(filename));
            oos.writeObject(this);
        } finally {
            if(oos != null)
            {
                oos.close();
            }
        }
    }
    public static JogoMaquinaEstados ler(String filename) throws IOException, ClassNotFoundException {
    ObjectInputStream oos = null;
        try {
            oos = new ObjectInputStream(new FileInputStream(filename));
            return (JogoMaquinaEstados) oos.readObject();
        } finally {
            if(oos != null)
            {
                oos.close();
            }
        }
    
    }
}

Tags : , ,

Programação avançada – capitulo 8 – maquina de estados, exemplo2

Exemplo de uma maquina de estado, simples, usando as referências a um mecanismo de um elevador com dois estados extra: erro e chaveManutencao

Em que ficou:

Com:

package me_me_elevador;

import me_me_elevador.IU.Texto.UsaElevador;
import me_me_elevador.logica.Elevador;

public class Me_ME_elevador {
    public static void main(String[] args) {
        Elevador e = new Elevador();
        UsaElevador usaE = new UsaElevador(e); //interface com o utilizador
        usaE.corre();
    }
}
package me_me_elevador.IU.Texto;

import me_me_elevador.logica.*;
import me_me_elevador.util.IUUtil;

public class UsaElevador {

    //o interface com o utilizador, com o nosso elevador.
    private Elevador elevador;
    private boolean sair = false;

    public UsaElevador(Elevador elevador) {
        this.elevador = elevador;
    }

    public void corre() {
        while (!sair) {
            //saber em que estado estou
            IEstado estado = elevador.getEstado();
            if (estado instanceof RC) {
                iuRC();
            } else if (estado instanceof Andar1) {
                iuAndar1();
            } else if (estado instanceof Andar2) {
                iuAndar2();
            } else if (estado instanceof Andar3) {
                iuAndar3();
            }else if (estado instanceof Manutencao) {
                iuManutencao();
            }
        }
    }
    
    
     private void iuManutencao() {
        int opcao = IUUtil.getOpcao("Em modo de manutenção", "Usar a chave", "Sair do elevador");
        switch (opcao) {
            case 0:
                elevador.chaveManutencao();
            case 1:
                sair = true;
                break;
        }
    }

    private void iuRC() {
        //opcoa 1
        //pedir ao utilizador: sair ou subir
        int opcao = IUUtil.getOpcao("Piso R/C", "Sair do prédio", "Subir", "Erro");
        switch (opcao) {
            case 0:
                sair = true;
                break;
            case 1:
                //fazer evoluir a maquina de estados
                elevador.sobe();
                break;
            case 2:
                elevador.erro();
                break;
        }
    }

    private void iuAndar1() {
        int opcao = IUUtil.getOpcao("Piso 1 andar", "Descer", "Subir", "Erro");
        switch (opcao) {
            case 0:
                //fazer evoluir a maquina de estados
                elevador.desce();
                break;
            case 1:
                //fazer evoluir a maquina de estados
                elevador.sobe();
                break;
            case 2:
                elevador.erro();
                break;
        }
    }

    private void iuAndar2() {
        int opcao = IUUtil.getOpcao("Piso 2 andar", "Descer", "Subir", "Erro");
        switch (opcao) {
            case 0:
                //fazer evoluir a maquina de estados
                elevador.desce();
                break;
            case 1:
                //fazer evoluir a maquina de estados
                elevador.sobe();
                break;
            case 2:
                elevador.erro();
                break;
        }
    }

    private void iuAndar3() {
        int opcao = IUUtil.getOpcao("Piso 3 andar", "Descer", "Erro");
        switch (opcao) {
            case 0:
                //fazer evoluir a maquina de estados
                elevador.desce();
                break;
            case 1:
                elevador.erro();
                break;
        }
    }
}
package me_me_elevador.logica;

public class Andar1 extends Piso {

    @Override
    public IEstado sobe() {
        //altero de estado
        return new Andar2();
    }

    @Override
    public IEstado desce() {
        //altero de estado
        return new RC();
    }
    
    //se fossem todos iguais podia ser implementado no Piso
    // com return this;
    @Override
    public IEstado erro() {
        return new Manutencao(this);
    }
}
package me_me_elevador.logica;

public class Andar2 extends Piso{

    @Override
    public IEstado sobe() {
        return new Andar3();
    }

    @Override
    public IEstado desce() {
        return new Andar1();
    }
    @Override
    public IEstado erro() {
                return new Manutencao(this);
    }
}
package me_me_elevador.logica;

public class Andar3 extends Piso{

    @Override
    public IEstado sobe() {
        //fico no mesmo estado
       return this;
    }

    @Override
    public IEstado desce() {
        //altero de estado
        return new Andar2();
    }
    @Override
    public IEstado erro() {
                return new Manutencao(this);
    }
}

package me_me_elevador.logica;

public class Elevador {
    IEstado estado;

    public Elevador() {
        estado = new RC();
    }

    public IEstado getEstado() {
        return estado;
    }
    public void setEstado(IEstado estado) {
        this.estado = estado;
    }
    public void sobe() {
        setEstado(estado.sobe());
    }

    public void desce() {
        setEstado(estado.desce());
    }
    
    public void erro(){
        setEstado(estado.erro());
    }
    
    public void chaveManutencao(){
        setEstado(estado.chaveManutencao());
    }
}

package me_me_elevador.logica;

public interface IEstado {
    IEstado sobe();
    IEstado desce();
    
    IEstado erro();
    IEstado chaveManutencao();
}

package me_me_elevador.logica;

public class Manutencao extends Piso{
    //vai recordar qual era o estado antes
    private IEstado anterior;

    public Manutencao(IEstado ant) {
        this.anterior = ant;
    }
    
    @Override
    public IEstado chaveManutencao() {
      return anterior;
    }   
}
package me_me_elevador.logica;

public abstract class Piso implements IEstado {
    @Override
    public IEstado sobe() {
        return this;
    }

    @Override
    public IEstado desce() {
        return this;
    }

    @Override
    public IEstado chaveManutencao() {
        return this;
    }

    @Override
    public IEstado erro() {
        return this;
    }
}
package me_me_elevador.logica;

public class RC extends Piso {

    @Override
    public IEstado sobe() {
        //altero de estado
        return new Andar1();
    }

    @Override
    public IEstado desce() {
        //fico no mesmo estado
        return this;
    }

    @Override
    public IEstado erro() {
        return new Manutencao(this);
    }
}

package me_me_elevador.util;

import java.util.Scanner;

public class IUUtil {
    public static int getOpcao(String question, String... options) {
        System.out.println(question);
        char[] ops = new char[options.length];
        for (int i = 0; i < options.length; i++) {
            char o = '\0';
            int c = 0;
            while (c < options[i].length()) {
                o = Character.toUpperCase(options[i].charAt(c));
                for (int j = 0; j < i; j++) {
                    if (ops[j] == o) {
                        o = '\0';
                        break;
                    }
                }
                if (o != '\0') {
                    break;
                }
                c++;
            }
            if (c >= options[i].length()) {
                return -1;
            }
            ops[i] = o;
            if (i > 0) {
                System.out.print(", ");
            }
            if (c > 0) {
                System.out.print(options[i].substring(0, c));
            }
            System.out.print("(" + ops[i] + ")" + options[i].substring(c + 1));
        }
        System.out.println();
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.print("Option: ");
            char o = Character.toUpperCase(sc.nextLine().charAt(0));
            for (int i = 0; i < ops.length; i++) {
                if (o == ops[i]) {
                    return i;
                }
            }
        }
    }
}

O erro e a chaveEmergencia são acções, sendo que o evento que surge é a Manutenção.

Tags : , ,

Programação avançada – capitulo 8 – maquina de estados, exemplo1

Exemplo de uma maquina de estado, simples, usando as referências a um mecanismo de um elevador

Em que ficou:

Com:

package me_me_elevador;

import me_me_elevador.IU.Texto.UsaElevador;
import me_me_elevador.logica.Elevador;

public class Me_ME_elevador {
    public static void main(String[] args) {
        Elevador e = new Elevador();
        UsaElevador usaE = new UsaElevador(e); //interface com o utilizador
        usaE.corre();
    }
}
package me_me_elevador.IU.Texto;

import me_me_elevador.logica.*;
import me_me_elevador.util.IUUtil;

public class UsaElevador {

    //o interface com o utilizador, com o nosso elevador.
    private Elevador elevador;
    private boolean sair = false;

    public UsaElevador(Elevador elevador) {
        this.elevador = elevador;
    }

    public void corre() {
        while (!sair) {
            //saber em que estado estou
            IEstado estado = elevador.getEstado();
            if (estado instanceof RC) {
                iuRC();
            } else if (estado instanceof Andar1) {
                iuAndar1();
            } else if (estado instanceof Andar2) {
                iuAndar2();
            } else if (estado instanceof Andar3) {
                iuAndar3();
            }
        }
    }

    private void iuRC() {
        //opcoa 1
        //pedir ao utilizador: sair ou subir
        int opcao = IUUtil.getOpcao("Piso R/C", "Ir embora", "Subir");
        switch (opcao) {
            case 0:
                sair = true;
                break;
            case 1:
                //fazer evoluir a maquina de estados
                elevador.sobe();
                break;
        }
    }

    private void iuAndar1() {
        int opcao = IUUtil.getOpcao("Piso 1 andar","Descer", "Subir");
        switch (opcao) {
            case 0:
                //fazer evoluir a maquina de estados
                elevador.desce();
                break;
            case 1:
                //fazer evoluir a maquina de estados
                elevador.sobe();
                break;
        }
    }

    private void iuAndar2() {
        int opcao = IUUtil.getOpcao("Piso 2 andar","Descer", "Subir");
        switch (opcao) {
            case 0:
                //fazer evoluir a maquina de estados
                elevador.desce();
                break;
            case 1:
                //fazer evoluir a maquina de estados
                elevador.sobe();
                break;
        }
    }

    private void iuAndar3() {
        int opcao = IUUtil.getOpcao("Piso 3 andar","Descer");
        switch (opcao) {
            case 0:
                //fazer evoluir a maquina de estados
                elevador.desce();
                break;
        }
    }
}
package me_me_elevador.logica;

public class Andar1 extends Piso{

    @Override
    public IEstado sobe() {
        //altero de estado
        return new Andar2();
    }

    @Override
    public IEstado desce() {
        //altero de estado
        return new RC();
    }
}
package me_me_elevador.logica;

public class Andar2 extends Piso{

    @Override
    public IEstado sobe() {
        return new Andar3();
    }

    @Override
    public IEstado desce() {
        return new Andar1();
    }
}
package me_me_elevador.logica;

public class Andar3 extends Piso{

    @Override
    public IEstado sobe() {
        //fico no mesmo estado
       return this;
    }

    @Override
    public IEstado desce() {
        //altero de estado
        return new Andar2();
    }
}
package me_me_elevador.logica;

public class Elevador {
//é a maquina de estados, que faz alterar os estados
    IEstado estado;

    public Elevador() {
        //o estado incial//arranque é então:
        estado = new RC();
    }

    public IEstado getEstado() {
        return estado;
    }

    public void setEstado(IEstado estado) {
        this.estado = estado;
    }

    //podia ter outras informações, como o numero de pessoas
    //as luzes que estão ou não ligadas..
    //métodos que dão origem à mudança de estado
    public void sobe() {
        setEstado(estado.sobe()); //versão1
        //this.estado = estado.sobe();  //versão2
    }

    public void desce() {
        setEstado(estado.desce()); //versão1
        //this.estado = estado.desce();  //versão2
    }
}
package me_me_elevador.logica;

public interface IEstado {
    //acções comuns a cada uma dos estados:RC,andar1,andar2...
    //interface geral
    IEstado sobe();
    IEstado desce();
}
package me_me_elevador.logica;

public abstract class Piso implements IEstado {
    //classe para implementação default, sem alterar o estado
    //serve para simplifcar todas as outras
    @Override
    public IEstado sobe() {
        return this;
    }

    @Override
    public IEstado desce() {
        return this;
    }
}
package me_me_elevador.logica;

public class RC extends Piso{

    @Override
    public IEstado sobe() {
        //altero de estado
        return new Andar1();
    }

    @Override
    public IEstado desce() {
        //fico no mesmo estado
        return this; 
    }
}
package me_me_elevador.util;

import java.util.Scanner;

public class IUUtil {
    // v1
      public static int getOpcao(String question, String... options) {
        System.out.println(question);
        char[] ops = new char[options.length];
        for (int i = 0; i < options.length; i++) {
            char o = '\0';
            int c = 0;
            while (c < options[i].length()) {
                o = Character.toUpperCase(options[i].charAt(c));
                for (int j = 0; j < i; j++) {
                    if (ops[j] == o) {
                        o = '\0';
                        break;
                    }
                }
                if (o != '\0') {
                    break;
                }
                c++;
            }
            if (c >= options[i].length()) {
                return -1;
            }
            ops[i] = o;
            if (i > 0) {
                System.out.print(", ");
            }
            if (c > 0) {
                System.out.print(options[i].substring(0, c));
            }
            System.out.print("(" + ops[i] + ")" + options[i].substring(c + 1));
        }
        System.out.println();
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.print("Option: ");
            char o = Character.toUpperCase(sc.nextLine().charAt(0));
            for (int i = 0; i < ops.length; i++) {
                if (o == ops[i]) {
                    return i;
                }
            }
        }
    }
}

No interface IEstado, são colocados todas as ações dos estados, mesmo que não façam sentido em alguns dos estados.
A class Piso, faz a implementação default de alguns dos estados para que não tenhamos que estar a repetir código nos diferentes estados.

Tags : , ,

Programação avançada – capitulo 7

A classe Object:
esta é a classe das quais todas as outras classes derivam
tem métodos importantes:
public String toString()
que retorna uma string que descreve um objeto

public boolean equals(Objecto obj)
tem com objectivo fazer a comparação entre dois objectos, em termos de conteudos, sabendo que usando o == compara referências
e é necessário que ele esteja definido

package e23;

class Animal{
    private int peso;
    private String nome;

    Animal(int p, String s){
        this.peso = p;
        this.nome = s;
    }
    
    public boolean equals(Object ob){
        if(this == ob){
            return true;
        }
        if((ob == null) || (ob.getClass() != this.getClass())){
            return false;
        }
        
        // type casting of the argument
        Animal anim = (Animal)ob;
    
        return (this.peso == anim.peso && this.nome == anim.nome);
    }

}

public class e23 {

    public static void main(String args[]) {
        Animal a1 = new Animal(80, "pedro");
        Animal a2 = new Animal(55, "maria");
        Animal a3 = new Animal(80, "pedro");
        
        if(a1.equals(a3)){
            System.out.println("O método equals");
        }else{
            System.out.println("Não são iguais");
        }
    }
}

public int hashCode()
quando se define o método equals também se deve definir o método hashCode()
este método retorna um inteiro, que resulta da conversão do endereço interno do objecto

package e23;

import java.util.Objects;

class Animal {

    private int peso;
    private String nome;

    Animal(int p, String s) {
        this.peso = p;
        this.nome = s;
    }

    public boolean equals(Object ob) {
        if (this == ob) {
            return true;
        }
        if ((ob == null) || (ob.getClass() != this.getClass())) {
            return false;
        }

        // type casting of the argument
        Animal anim = (Animal) ob;

        return (this.peso == anim.peso && this.nome == anim.nome);
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 17 * hash + this.peso;
        hash = 17 * hash + Objects.hashCode(this.nome);
        return hash;
    }
}

public class e23 {

    public static void main(String args[]) {
        Animal a1 = new Animal(80, "pedro");
        Animal a2 = new Animal(55, "maria");
        Animal a3 = new Animal(80, "pedro");

        if (a1.equals(a3)) {
            System.out.println("O método equals");
        } else {
            System.out.println("Não são iguais");
        }
    }
}

Este método como outros podem ser inseridos de forma automática no netbeans, se dentro da classe e com o lado direito do reato se optar por inserir código (ALT+INSERT)

+infos(geeksforgeeks.org): LINK gostei da explicação

Tags : , , ,

Programação avançada – capitulo 6

O upcasting:
serve para realizar a conversão de tipo, de uma classe derivada para uma classe base
permite assim converter um tipo mais restrito num tipo mais alargado

O polimorfismo:
“O mecanismo de polimorfismo consiste na qualidade de poder decidir a operação que vai ser executada num dado instante , em função dos objetos específicos envolvidos na operação”

As classes abstractas:
um método é abstracto, se o seu prototípico for escrito precedido da palavra abstract
uma classe que tenha um método abstracto tem que ser declarada como abstracta
não se podem criar objectos em classes abstractas
uma classe pode ser abstracta, mesmo não tendo qualquer método abstracto (caso de uma classe derivada de uma abstracta)
uma classe derivada não é abstracta se tiver definidos todos os métodos da classe abstracta
uma classe derivada é abstracta se não tiver pelo menos um método da classe base

exemplo (especialização: do topo para a base, generalização: da base para o topo (sentido das setas)):

package e16;

abstract class Veiculo {
    abstract int calculaCarro();
    abstract int calculaAutocarro();
}

//errada esta classe Carro.. se é abstracta só deveria ter protótipos das funções
abstract class Carro extends Veiculo {
    private int km;
    private int custo = 5;

    public Carro(int k) {
        this.km = k;
    }
    int calculaCarro() {
        int valor = this.km * custo;
        return valor;
    }
    public String toString() {
        return "despesa do carro: " + calculaCarro();
    }
}

class Autocarro extends Veiculo {
    private int km;
    private int custo = 4;

    public Autocarro() { //importante - parte1
    }
    public Autocarro(int k) {
        this.km = k;
    }
    int calculaAutocarro() {
        int valor = this.km * custo;
        return valor;
    }
    int calculaCarro() {
        int valor = this.km * custo;
        return valor;
    }
    public String toString() {
        return "despesa do autocarro: " + calculaAutocarro();
    }
}

class MiniAutocarro extends Autocarro {
    private int km;
    private int custo = 1;

    public MiniAutocarro() { //importante - parte2
    }
    public MiniAutocarro(int k) {
        this.km = k;
    }
    int calculaMiniAutocarro() {
        int valor = this.km * custo;
        return valor;
    }
    public String toString() {
        return "despesa do mini-autocarro: " + calculaMiniAutocarro() + " , " + super.toString();
    }
}

public class e16 {

    public static void main(String args[]) {
        System.out.println("\n Classe abstracta:"); //sout+tab
        Veiculo v1;
        v1 = new Autocarro(100);
        System.out.println(v1.toString());
        Veiculo v2;
        v2 = new MiniAutocarro(200);
        System.out.println(v2.toString());
    }
}

As interfaces:
é outra forma de trabalhar com classes abstractas
a interface pode conter: constantes, ou métodos
para definir uma classe que tem um ou mais interfaces, faz-se uso da expressão implements
os membros variáveis são implicitamente: public, final ou static (e é redundante usar estas expressões)
os métodos são public (e é redundante indicar)
uma classe só deriva de outra classe, e pode ter vários interfaces
várias classes podem implementar um interface

package e17;

interface Livro {
    void oLivro(int paginas);
}

interface Comic {
    void acerca(int paginas);
}

class Policial implements Livro {
    public void oLivro(int p) {
        System.out.println("\nChamada com " + p + " no Policial");
    }
    void maisInformacao() {
        System.out.println("\nOutras informacações no Policial");
    }
}

class Marvel extends Policial implements Comic{
    public void acerca(int p){
        System.out.println("\nOutras informacações na Marvel: " +p);
    }
}

public class e17 {
    public static void main(String args[]) {
        Marvel v = new Marvel();
        v.acerca(2);
        v.maisInformacao();
        
        Policial p = new Policial();
        p.oLivro(10);
        p.maisInformacao();
    }
}

Podem existir referências para um interface, é usado o mecanismo de polimorfismo, e nele podem ser referidos objetos de uma classe que o implementem, e faz uso apenas dos métodos da classe declarados na interface
se uma classe for interface, e não forem definidos todos os métodos que são abstractos, essa classe passa a ser abstracta

package e18;

interface Jogos {
    void precoJogos(int preco);
    void qualidadeJogos(int qualidade);
}

class jogoTabuleiro implements Jogos {
    public void precoJogos(int p) {
        System.out.print("\njogo de tabueliro" + p);
    }
    public void qualidadeJogos(int q) {
        System.out.print("\njogo de tabueliro" + q);
    }
}

abstract class jogoDigital implements Jogos {
    void oJogoDigital(int j) {
        System.out.print("\njogo de tabueliro" + j);
    }
}

class jogoDigitialOficial extends jogoDigital {

    public void oJogoDigital() {
        System.out.print("\njogo digital");
    }

    public void precoJogos(int preco) {
    }; //obrgatorio
    public void qualidadeJogos(int qualidade) {
    } //obrgatorio
}

public class e18 {
    public static void main(String args[]) {
        jogoDigitialOficial jd = new jogoDigitialOficial();
        jd.oJogoDigital();
    }
}

Nas interfaces podem surgir os métodos default
O default define uma implementação por omissão desse métodos, para todas as classes que implementam o interface e que não definam a sua própria implementação
Um método defualt não pode ser abstract nem static

package e19;

interface jogosDigitais {

    void contaJogadores(int n);

    default void precoAtual(int preco) {
        int conta = preco * 2;
        contaJogadores(conta); //pode fazer uso de outros métodos da interface
    }
}

class RTS implements jogosDigitais {

    private int jogadores;

    public void contaJogadores(int ct) {
        this.jogadores = ct;
    }
    
    //redefinição do métdo default
    public void precoAtual(int p){
        contaJogadores(10);
    }
    

    public String toString() {
        return "resultado " + jogadores;
    }
}

public class e19 {
    public static void main(String args[]) {
        jogosDigitais jd1 = new RTS();
        jd1.precoAtual(4);
        System.out.print(jd1);
        jd1.toString(); //nao entendo porque este método não é reproduzido
    }
}

Nas interfaces podem surgir os métodos static
um método static numa interface tem que definir uma implementação
não existe overide nas classes que implementam uma interface com métodos static
o static pode ser usado na interface, para incluir métodos utilitários

package e20;

interface Quadro {

    void ilustrar(int il);

    static void calculo(int valor) {
        valor = valor * 1;
    }
}

class corRGB implements Quadro {

    private int corRGB = 123;

    corRGB() {
        this.corRGB = corRGB;
    }

    public void ilustrar(int i) {
        this.corRGB = i * i * i;
    }

    public String toString() {
        return "do quadro surge " + corRGB;
    }
}

public class e20 {

    public static void main(String args[]) {
        Quadro q1 = new corRGB();
        q1.ilustrar(20);
        System.out.print(q1);
    }
}

Nas interfaces podem surgir constantes que são utilizadas, como utilitárias nas classes derivadas

package e21;

interface valores {
    int EURO = 2;
    int DOLAR = 1;
}

class banco implements valores {

    private int contas;

    banco() {
        this.contas = EURO + DOLAR;
    }
    public String toString() {
        return "das contas surge " + contas;
    }
}

public class e21 {

    public static void main(String args[]) {
        banco b1 = new banco();
        System.out.print(b1);
        b1.toString(); // não é executada e não compreendo do porquê!
    }
}

E também uma interface pode derivar de outras interfaces:
a interface derivada que tenha constantes com o mesmo nome da interface herdada, a que é herdade não é “escondida”
a interface derivada herda todos os métodos abstract e default
a interface derivada não herda os métodos que forem static

package e22;

interface Mae {

    int valor = 10;
    int total = -10;

    static int fala() {
        return valor * 2;
    }

    default int comida() {
        return valor * 3;
    }

    abstract int correr();
}

interface Pai {

    int valor = 20;
    int total = -20;

    static int fala() {
        return valor * 2;
    }

    default int comida() {
        return valor * 3;
    }

    abstract int correr();
}

interface Filha extends Pai, Mae {

    int comida();
}

class Neto implements Filha {

    public int comida() {
        return Mae.valor + Pai.total;
    }

    public int correr() {
        return Mae.total + Pai.valor;
    }
}

public class e22 {

    public static void main(String args[]) {
        Filha f1 = new Neto();
        System.out.println("estatico " + f1.correr()); //20
        System.out.println("estatico " + f1.comida());//-10

    }
}

Como sempre gostei de gráficos aqui fica:

+infos(fonte dos gráficos): LINK

Tags : , , ,

Programação avançada – capitulo 5

A composição e a herança:
por composição: quando temos uma classe cujos membros são referências para objetos de outras classes
por herança: quando se cria uma classe que seja de um tipo de uma classes que já existe (uma especialização). Quando não existe uma derivação vamos estar a criar uma classe derivada da class Object, sendo que esta classe é a classe base de uma hierarquia a que todas as classes em Java pertencem
Na herança, isto é na classe derivada, para se fazer uso de métodos da classe base temos que usar a expressão super (caso tenham o mesmo nome)

Um exemplo de composição:

package e13;

class Pagina {

    private int numero;
    private int quantidadePalavras;

    public Pagina() {
        this(1, 100);
    }

    public Pagina(int n, int qp) {
        numero = n;
        quantidadePalavras = qp;
    }

    @Override
    public String toString() {
        return "\n Pagina " + " numero " + numero + " quantidade paginas " + quantidadePalavras;

    }
}

class Livro {

    private boolean capa;
    private Pagina pagina;

    public Livro() {
        this(false, 2, 200);
    }

    public Livro(boolean c, int n, int qp) {
        capa = c;
        pagina = new Pagina(n, qp);
    }

    @Override
    public String toString() {
        return "\ncapa " + capa + " pagina livro " + pagina;
    }
}

public class e13 {

    public static void main(String args[]) {
        System.out.println("\n A composição de classes:");
        Livro l1 = new Livro();
        System.out.println("\n surge:" + l1);
        Livro l2 = new Livro(true, 3, 300);
        System.out.println("\n surge:" + l2);
    }
}

Um exemplo de Herança:

package e13;

class Pagina {

    private int numero;
    private int quantidadePalavras;

    public Pagina() {
        this(1, 100);
    }

    public Pagina(int n, int qp) {
        numero = n;
        quantidadePalavras = qp;
    }

    protected void setNumeroPagina(int p) {
        numero = p;
    }

    protected int getNumeroPagina() {
        return numero;
    }

    protected void setQuantidadePalavras(int qp) {
        quantidadePalavras = qp;
    }

    protected int getQuantidadePalavras() {
        return quantidadePalavras;
    }

    @Override
    public String toString() {
        return "\n Pagina " + " numero " + numero + " quantidade paginas " + quantidadePalavras;
    }
}

class PaginaComCores extends Pagina {

    private boolean cor;

    public PaginaComCores() {
        this(false);
    }

    public PaginaComCores(boolean c) {
        cor = c;
    }

    protected void setCor(boolean c) {
        cor = c;
    }

    protected boolean getCor() {
        return cor;
    }

    @Override
    public String toString() {
        return "\n PaginaComCores " + super.toString() + ", cor " + cor;
    }
}

public class e13 {

    public static void main(String args[]) {
        System.out.println("\n A herança de classes:");
        Pagina p1 = new Pagina();
        System.out.println(p1);
        PaginaComCores p2 = new PaginaComCores(true);
        System.out.println(p2);
    }
}

Escolher entre composição e derivação:
se um objecto contem objectos de outra classe – composição ( …”contém” …)
se um objecto é especializado de outra classes – derivação/herança ( … “é” …)

O uso de constantes de classe, pode se aplicado através do modificador final
O final associado a uma variável, torna a variável constante
O final associado a uma referência, torna a referência constante
O final associado a um método, impede que uma derivada possa redefinir esse método
O final associado a uma classe, impede que essa classe seja derivada

package e14;

class Pagina {

    private int numero0 = 0;
    private final int numero1 = 1;
    static final int numero2 = 2;
    public static final int numero3= 3;

    
    void setnumero0(int n0){
        numero0=n0;
    }
    
    int getNumero0(){
       return numero0; 
    }
    
    public Pagina() {
        
    }
 
    @Override
    public String toString() {
        return "\n Pagina " + " numero " + numero1 + " - " + numero2  + " - " + numero3;
    }
}


public class e14 {

    public static void main(String args[]) {
        System.out.println("\n O uso da expressão final:");
        Pagina p1 = new Pagina();
        p1.setnumero0(9);
        System.out.println(p1.getNumero0());
      
    }
}

Exemplo de erro aplicado a uma classe e construção de uma derivada

//v1
package e14;

final class Pagina {

    private int numero0 = 0;
    private final int numero1 = 1;
    static final int numero2 = 2;
    public static final int numero3= 3;

    
    void setnumero0(int n0){
        numero0=n0;
    }
    
    int getNumero0(){
       return numero0; 
    }
    
    public Pagina() {
        
    }
 
    @Override
    public String toString() {
        return "\n Pagina " + " numero " + numero1 + " - " + numero2  + " - " + numero3;
    }
}

class PaginaACores extends Pagina{
    boolean cores;
    
    PaginaACores(){
    
    }
    
}

public class e14 {

    public static void main(String args[]) {
        System.out.println("\n O uso da expressão final em classes:");

      
    }
}
Tags : , , , , , , , , ,

Programação avançada – capitulo 4

Um package é um agrupamento de classes com algum significado em comum.
Num ficheiro de código fonte pode existir uma classe publica que deve ter o mesmo nome do ficheiro, sendo que só pode haver uma única classe publica em cada ficheiro de código fonte
Os package podem ter outros package por referência, isto é, podemos ter uma estrutura de um package declarado do tipo package pkg1.pkg2.kg3; e que está gravado pkg1\pkg2\pkg3
A instrução import permite identificar classes pertencentes a outros packages sem ser necessário indicar o caminho até ao interior do package

As classes só podem ter um de dois níveis de acesso:
publico
ou por defeito (sem especificador)

Podemos aceder aos membros das classes com a seguinte organização (private, sem especificador, protected, public):

A organização em packages permite:
evitar situações de problemas onde existem classes com o mesmo nome, mas com significados diferentes
proporcionar segurança nos diferentes níveis de visibilidade

 

 

Tags : , , , ,

Programação avançada – capitulo 3

Objetos
A palavra new permite criar novos objetos
Os delimitadores dos { } permitem define o scope dos objetos

Em java existe o Garbage collector, que detecta todos os objetos que foram criados por new e que já não são referenciados em memória, libertanto desta forma o espaço em memória correspondente (esta dinâmica não existe noutras linguagens como em C, ou o destrutor em C++)

Um classe é constituída por:
membros variáveis (do tipo primitivos ou referências para objetos) Para se usar os membros de um determinado objeto faz-se uso do . (ponto final)
por métodos (podem existir métodos com o mesmo nome na mesma classe, são os métodos overloaded )
por um ou mais construtores (é a forma de garantir a inicialização de todos os objetos de uma classe, e o construtor não pode ser chamado por um seu método)

package e08;

class Texto{
    String palavras;
    int numero_paginas;
    
    Texto(){
        palavras = "vazio";
        numero_paginas = 0;
    }
    
    Texto(String p, int n_p){
        palavras = p;
        numero_paginas = n_p;
    }
    
    boolean valida(int n_p){
        if(n_p <=0){
            return false;
        }
        return true;
    }
}

public class e08 {

    public static void main(String args[]) {
        System.out.println("\n O uso de classes");
        Texto t1 = new Texto();
        System.out.println("\n construtor por defeito: " + t1.numero_paginas + " - " + t1.palavras);
        Texto t2 = new Texto("pedro", 100);
        System.out.println("\n construtor overloaded: " + t2.numero_paginas + " - " + t2.palavras);
        
    }
}

A palavra chave this:
Permite aceder a uma variável ou a um método do próprio objeto
o this também pode ser usado dentro de um construtor, o this faz uma chamada explicita ao construtor (com ou sem argumentos)
um construtor pode então desta forma ser chamado a partir de outro construtor

package e09;

class Texto{
    String palavras;
    int numero_paginas;
    
    Texto(){
        this("vazio", 100);
    }
    
    Texto(String p, int n_p){
        palavras = p;
        numero_paginas = n_p;
    }
    
    boolean valida(int n_p){
        if(n_p <=0){
            return false;
        }
        return true;
    }
}

public class e09 {

    public static void main(String args[]) {
        System.out.println("\n O uso da referência especial this");
        Texto t1 = new Texto();
        System.out.println("\n construtor por defeito: " + t1.numero_paginas + " - " + t1.palavras + " - " + t1.valida(t1.numero_paginas));
    }
}

São membros static:
Aquelas variáveis ou os membros que não estão ligados a qualquer objeto em particular
Só existe uma versão de um membro variável estático, partilhada por todos os objetos
Antes de se criar um objeto, podemos executar o método static ou aceder a qualquer variável static
Os métodos static, não têm a referência a this
Não se pode aceder directamente a variáveis ou métodos não estáticos (pois eles estão sempre ligados a um objeto em particular, e assim só se pode aceder a membros não estáticos se for invocado a partir de um objeto)

package e10;

class Texto {

    String palavras;
    static int numero_paginas = -1;

    Texto() {
        this("vazio", 100);
    }

    Texto(String p, int n_p) {
        palavras = p;
        numero_paginas = n_p;
    }

    static boolean valida(int n_p) {
        if (n_p <= 0) {
            return false;
        }
        return true;
    }
}

public class e10 {

    public static void main(String args[]) {
        System.out.println("\n membros static");
        System.out.println("\n aceder ao métodos antes do objeto: " + Texto.valida(100));
        Texto t1 = new Texto();
        System.out.println("\n aceder ao métodos depois do objeto: " + t1.valida(Texto.numero_paginas));
    }
}

A inicialização
Os membros variáveis das classes se forem usados sem estarem inicializados vão dar erro
É preferível inicializar essas variáveis ou então fazê-lo no construtor, com valores pode defeito
Se forem membros estáticos, eles são inicializados apenas uma vez, quando a classe for usada pela primeira vez
Nos objetos:
são inicializados os membros variáveis e depois o construtor

package e11;

class Texto {

    String palavras;
    int numero_paginas = -1;

    Texto() {
        palavras = "vazio original";
        System.out.println("\n construtor do texto: " + palavras);
    }

    Texto(String p, int n_p) {
        palavras = p;
        numero_paginas = n_p;
        System.out.println("\n segundo construtor do texto: " + palavras);
    }

    static boolean valida(int n_p) {
        if (n_p <= 0) {
            return false;
        }
        return true;
    }
}

class Livro {
    Texto t1 = new Texto("no livro", 100);

    Livro() {
        System.out.println("\n construtor do Livro: " + t1.palavras);
    }
    
    void mostra(){
        System.out.println("\n mostra do Livro");
    }
    static Texto t2 = new Texto("static no livro", 100); //primeiro a ser executado
}

public class e11 {

    public static void main(String args[]) {
        System.out.println("\n inicialização:");
        Livro l1 = new Livro();
        System.out.println("\n no main:" + l1.t1.palavras);
        l1.mostra();

    }
}

Tags : , , , , , , , , , , , , ,

Programação avançada – capitulo 2

Acerca dos tipos primitivos:
foi removida a noção de unsigned

O Java faz uso do unicode

Existe o Boxing e o Unboxing em Java, sendo que um exemplo de Boxing é o da substituição automaticamente por um objeto da classe wrapper correspondente, isto é:

public class e01 {
    public static void main(String args[]){
            System.out.println("\n Primeiro exemplo de Java");
            Integer a = 100;
            Integer a2 = new Integer(101);
            int b = 200;
            System.out.println(a + " - " + b + " - " + a2);
            
        }
}

Os arrays de tipos primitivos:
podem conter tipos primitivos
ou
referências para objetos

Existem duas formas de os representar:
int [] agora;
ou
int ontem[];

public class e02 {
    public static void main(String args[]){
            System.out.println("\n Os arrays em Java");
            int [] antes = new int[12]; //para criar: reservar espaço em memória
            int depois [] = {1,2,3,4,5,6,7,8,9}; //array reservado em memória dinamicamente, atribuição de arrays
            
            antes[0] = 0;
            
            System.out.println("\n Aceder a um elemento do array: " + antes[0]);
            System.out.println("\n Aceder a um elemento do array: " + depois[1]);
            
            System.out.println("\n Aceder ao total de elementos do array: " + antes.length);
            System.out.println("\n Aceder ao total de elementos do array: " + depois.length);
            
            //copiar arrays
            int [] copy = {0,1,3};
            int [] paste = new int[3]; //tem que ter o tamanho do copy
            System.arraycopy(copy, 0, paste, 0, copy.length);
            
            System.out.println("\n Aceder ao total de elementos do array depois de copiado: " + paste[1]);
        }
}

Os arrays como argumentos de métodos

public class e03 {
    static boolean arraysiguais(int []c, int []p){
        if(c.length != p.length){
            return false;
        }
        for(int i=0; i < c.length; i++){
            if(c[i] != p[i]){
                return false;
            }
        }
    return true;
    }
    
    public static void main(String args[]){
            System.out.println("\n Os arrays em Java: arrays como argumentos de métodos");
            int [] copy ={100,200,300};
            int [] paste = new int [3];
            
            //preencher cada um dos arrays
            for(int i=0; i< copy.length ;i++){
                copy[i]=i*i;
            }
            for(int i=0; i< paste.length ;i++){
                paste[i]=i*i*i;
            }
            
            if(arraysiguais(copy, paste)){
                System.out.println("\n Iguais");
            }else{
                System.out.println("\n Diferentes");
            }
        }
}

Os arrays como retorno de métodos:

public class e04 {

    static int[] arrayRetorno(int []a, int b[]){
        int extra[]= new int[Math.min(a.length, b.length)];
        
        for(int i=0; i< extra.length; i++){
            extra[i]=a[i]*b[i];
        }
     return extra;   
    }
    
    public static void main(String args[]){
            System.out.println("\n Os arrays em Java: arrays retorno de métodos");
            int arg1[] = {1,2,3};
            int arg2[] = {3,2,1};
            int argC[];
            
            argC = arrayRetorno(arg1, arg2);
            
            for(int i = 0; i< argC.length; i++){
                System.out.println("\n infos: " + argC[i]);
                
            }
        }
}

Os arrays multidmensionais:

public class e05 {
    static int[][] preenche(int a[][]){
        int aux[][]=new int[a.length][a[0].length];
        
        if(a.length ==0 || a[0].length==0){
            return null;
        }
        
        for(int i=0; i< a.length; i++){ //numero de linhas
            for(int j=0; j< a[i].length; j++){ //numero de colunas
                aux[i][j]=(i+1)*(j+1);
            }
        }
        return aux;
    }
    static void mostra(int a[][]){
        System.out.println("\n numero de linhas:" + a.length);
        System.out.println("\n numero de colunas:" + a[0].length);
        for(int i=0; i< a.length; i++){ //numero de linhas
            for(int j=0; j< a[i].length; j++){
                System.out.println(a[i][j]);
            }
            System.out.println("\n");
        }
    }
    public static void main(String args[]){
            System.out.println("\n Os arrays em Java: arrays multidimensionais");
            
            int multi[][] = new int[2][3];
            multi=preenche(multi);
            mostra(multi);
        }
}

Os operadores podem ser aplicados a todos os tipos de primitivos (int, float,…) contudo existem operadores que se podem aplicar a objetcos (referências para, cópia da referência) e que são:
=
==
!=
outros operadores que também funcionam com a classe String:
+
+=

Exemplo da passagem de um objecto por referência:

class Texto {
    String txt = "ola Java";
}

public class e06 {
    static void funcao(Texto t) {
        t.txt = "Dentro";
    }
    public static void main(String args[]) {
        System.out.println("\n Passagem de objetos a funções");
        Texto txt1 = new Texto();
        txt1.txt = "Ola Mundo";
        System.out.println("\n primeira versão: " + txt1.txt);
        funcao(txt1);
        System.out.println("\n segunda versão: " + txt1.txt);
    }
}

Exemplo do uso do operador equals:

class Texto {
    String txt = "ola Java";
}

public class e06 {
    static void funcao(Texto t) {
        t.txt = "Dentro";
    }
    public static void main(String args[]) {
        System.out.println("\n Passagem de objetos a funções");
        Texto txt1 = new Texto();
        Texto txt2 = new Texto();
        txt1.txt = "Ola Mundo";
        
        System.out.println("\n primeira versão: " + txt1.txt);
        funcao(txt1);
        System.out.println("\n segunda versão: " + txt1.txt);
        
        //operador equals
        txt2.txt = "Ola Mundo!!!";
        System.out.println("\n comparação: " + txt1.txt.equals(txt2.txt));
    }
}

O método equals não poderia ser usado com o objecto txt1 e txt2, porque ele não estava redefinido dentro da classe Texto.

Existem também o operador cast, e que é utilizado para:
conversões de tipos de maior para tipos de menor capacidade
ou outro casos em que não seriam feitas conversões implícitas

public class e07 {
    public static void main(String args[]) {
        System.out.println("\n Conversões de tipo");
        System.out.println("\n uma conversão implicita");
        int a = 100;
        float b;
        b = a;
        System.out.println("\n a: " + a + "\t b: " + b);
        
        System.out.println("\n uma conversão explicita (cast)");
        float d = 200;
        int e;
        e= (int)d;
        System.out.println("\n d: " + d + "\t e: " + e);
    }
}

Para testar um determinado tipo de objeto podemos fazer uso do instanceof

class Testar{
    char t= 'p';
}

public class e07 {

    public static void main(String args[]) {
        System.out.println("\n Testar o tipo de objeto");
        Testar t = new Testar();
        System.out.println(t instanceof Testar);
    }
}

Existe aqui também uma variante do ciclo for, que é o foreach, e que pode ser utilizado com arrays e coleções

public class e07 {

    public static void main(String args[]) {
        System.out.println("\n O ciclo for(each)");
        int i[]={0,1,2,3,4,5,6,7,8,9};
        for(int aux: i){
            System.out.println(i[aux]);
        }
    }
}

por vezes é importante fazer uso das instruções continue e break, sendo que quando o break é executado dentro de um ciclo, o ciclo termina e a execução continua na instrução a seguir
já o uso do continue, dentro de um ciclo while ou do while, termina a iteração corrente, continuando o ciclo a ser executado na iteração seguinte.
o uso do continue, dentro de um ciclo for, provoca a passagem ao incremento do ciclo e em seguida à avaliação da expressão condicional.
podem ser usados label com o caso do “:” (sem aspas) que serve para identificar ciclos do tipo: for, while ou do while

public class e07 {

    public static void main(String args[]) {
        System.out.println("\n a intrução do break e do continue");
        int i[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        System.out.println("\n primeira estrutura");
        primeiro:
        for (int aux : i) {
            if (aux > 5) {
                break primeiro; //ou break;
            }
            System.out.println(i[aux]);
        }
        System.out.println("\n segunda estrutura");
        segundo:
        for (int aux2 : i) {
            if (aux2 > 5) {
                System.out.println(i[aux2]);
            }
            if (aux2 == 8) {
                System.out.println("\n na segunda estrutura");
                continue segundo;
            }
        }
    }
}
Tags : , , , , , , , ,