terça-feira, 26 de março de 2013

Encapsular campos em Python 3.x

Encapsulamento de dados é um recurso presente em linguagens que seguem o paradigma orientado a objetos. Esse recurso tem como objetivo restrigir o acesso direto a informação, ou seja, ele protege informações que não devem ser alteradas em qualquer parte do programa. Com isso podemos entender que quem está de fora apenas sabe que o serviço é realizado mas não sabe como o serviço é implementado.

Certamente quando começamos a programar orientado a objetos não vemos os benefícios que o encapsulamento de dados nos proporciona, pois, a primeira vista ele só serve para gerar mais linhas de código.

Hoje vou falar como encapsular dados na linguagem de programação Python versão 3.x. Se você já programou em alguma linguagem .Net (Visual Basic, C#) não sentirá grandes mudanças, porém, se você é um programador Java sentirá uma certa estranheza quando ler o código.

Bom sem mais demora vamos conhecer mais um pouquinho da linguagem Python e sua implementação diferente em POO.

Protegendo minhas variáveis dos Noobs

Na minha opinião o encapsulamento de dados existe, porém, não garante a total segurança do seu código. Antes de você me chamar de louco vou explicar, se você é um programador Java e ficou muito ofendido com o que eu disse ... me desculpe essa não foi a intenssão! Mas Sr.Programador Java, seu código não está seguro só porque o Sr. usa o modificador de acesso private em suas variáveis de instância, se alguém quiser saber quais são as variáveis presentes em determinadas classes de seu sistema ele pode fazer isso utilizando a própria API do Java a nossa querida Reflection. Logicamente que trabalhar com essa API não é algo trivial, porém, pense duas vezes antes de desafiar um nerd dizendo que seu código está 100% seguro.

Em Python a história também não é diferente, se alguém quiser saber quais variáveis sua classe tem essa pessoa vai acabar descobrindo de um jeito ou de outro. Por isso que a ideia principal de Python é que tudo seja public e somente o necessário, seja private. Muitas vezes quando estamos aprendendo POO o pessoal costuma dizer: "Grande parte das vezes sua classe terá atributos de instância privado e métodos públicos". Mais nem sempre é assim, podemos realmente ter variáveis em nossas classes que não precisam serem private.

Bom, se você está certo que precisa ter variáveis private em sua classe e não quer que ela seja acessível fora da classe onde ela foi especificada, então você terá que informar primeiramente que ela será private, para que o interpretador Python saiba disso. Para dizer que um atributo de instância é private em python utilizamos dois underline antes do nome da variável. Exemplo:

class Gato:
    __raca = None
    ...

Com isso dizemos ao interpretador que o atributo raça é privado. Agora temos que construir dois métodos, um para setar (setter) e outro para recuperar (getter) o valor do atributo. No python 3.x foi introduzida uma sintaxe muito elegante para realizar esse serviço. Veja:

class Gato:
    def __init__(self):
        __raca = None

    @property
    def raca(self):
        return __raca

    @raca.setter
    def raca(self, value):
        self.__raca = value

Viu como é simples? Bom o que fizemos foi definir dois métodos (em python pode-se falar função da classe), onde no primeiro definimos o getter e o segundo o definimos o setter. Observe que os dois métodos tem o mesmo nome, mas possuem anotações diferentes. A primeira anotação @property indica o método é um getter e a segunda anotação @raca.setter indica que o método é um setter,  perceba que a segunda anotação é bem diferente da primeira, nela devemos informar o nome do atributo seguido de ponto e a palavra setter.

Podemos definir que um atributo seja apenas read-only. Para fazer isso basta excluir o método setter. Veja:

class Gato:
    def __init__(self):
        __raca = None

    @property
    def raca(self):
        return __raca

Agora observe como fica natural o acesso aos atributos:

if __name__ == '__main__':
    mimo = Gato()
    megui = Gato()

    mimo.raca = 'angorá turco'
    mimo.idade = 2

    megui.raca = 'siames'
    megui.idade = 1

    print('Megui é da raça {}, e tem {} ano(s) de idade.'.format(megui.raca, megui.idade))
    print('Mimo é da raça {}, e tem {} ano(s) de idade.'.format(mimo.raca, mimo.idade))

Pessoal o post se encerra por aqui! Espero que tenham gostado de aprender um pouco mais sobre Python e veja vocês em um próximo post, até lá e BONS ESTUDOS!

terça-feira, 19 de março de 2013

MinhaString & MinhaData

Fala pessoal, se você acompanha o blog e quando lê esses posts que não explicam absolutamente nada e que apenas possuem códigos e enunciados saiba que eles fazem parte das listas de exercícios da faculdade que eu curso (Instituto Federal de Educação, Ciência e Tecnologia de São Paulo - campus Araraquara). Bom hoje vou postar mais um  desses exercícios, porém, leia o código copie e execute ai na sua máquina, aproveite para brincar e descobrir o que ele faz ... isso te dará um conhecimento extra que muitas vezes deixamos escapar em uma explicação mais formal. Beleza?!

Enunciados:


A classe MinhaData está muito simples, implemente as seguintes melhorias:
  • Não permitir que uma data inválida seja instanciada. Caso tente-se instanciar uma data inválida instancie 01/01/1900.
  • Implemente um construtor que aceite várias ordens de argumentos parainstanciar uma data. Por exemplo, o mesmo construtor deve receber osseguintes dados: (1, 2, 1900) ou (1900, 2, 1) e instanciar a data 01/02/1900.
  • Implementar um método que retorne a data por extenso.
  • Implementar um método que retorne a quantidade de dias entre a data instanciada e uma data passada como argumento.
A classe MinhaString:
  • Sabe-se que em Java ou mesmo em C não existe um tipo primitivo para armazenar uma String. Implemente a classe MinhaString que permita manipular um conjunto de até 256 caracteres. Implemente todas as funcionalidades que acharem interessante para esta classe, como por exemplo: converter para maiúsculo, inverter o texto, comparar dois textos.

MinhaData.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package logica;

/**
 *
 * @author guilherme
 */
public class MinhaData {
    private int dia;
    private int mes;
    private int ano;

    public MinhaData(int param1, int param2, int param3, String mascara) {
        organizaValores(mascara, param1, param2, param3);
    }

    private void confereData(int dia, int mes, int ano) {
        boolean dataValida = true;
     
         /* Verifica ano */
        if(ano < 0) {
            dataValida = false;
        } else {
            this.ano = ano;
        }
     
        if(mes < 0 || mes > 12) {
            dataValida = false;
        } else {
            this.mes = mes;
        }
     
        /* Verifica se o dia é válido */
        if(dia > 1 && dia < 31) { //verifica se o dia não é negaivo
            if(mes == 2) {
                if(dia < 28 || (dia == 29 && anoBissexto(this.ano))) {
                    this.dia = dia;
                } else {
                    dataValida = false;
                }
            } else if(mes == 1 || mes == 3 || mes == 5 || mes == 7 || mes == 8
                    || mes == 10 || mes == 12) {
                    this.dia = dia;
            } else {
                if(dia > 30) {
                    dataValida = false;
                }
                this.dia = dia;
            }
        } else {
            dataValida = false;
        }
     
        /* Se a data não for válida então aplica-se a data padrão */
        if(!dataValida) {
            this.dia = 1;
            this.mes = 1;
            this.ano = 1990;
        }
     
    }
 
    private boolean anoBissexto(int ano) {
        if(ano % 4 == 0 && (ano % 100 != 0 || ano % 400 == 0)) {
            return true;
        }
        return false;
    }
 
    public String imprimeData(String padrao) {
        switch(padrao.toLowerCase()) {
            case "pt-br":
                return dia + "/" + mes + "/" + ano;
            case "us":
                return ano + "-" + mes + "-" + dia;
            default:
                return null;
        }
    }

    private void organizaValores(String mascara, int param1, int param2, int param3) {
        switch(mascara) {
            case "ymd":
                confereData(param3, param2, param1);
                break;
            case "ydm":
                confereData(param3, param1, param2);
                break;
            case "myd":
                confereData(param2, param3, param1);
                break;
            case "mdy":
                confereData(param2, param1, param3);
                break;
            case "dmy":
                confereData(param1, param2, param3);
                break;
            case "dym":
                confereData(param1, param3, param2);
                break;
            default:
                confereData(0, 0, 0);
                System.out.println("Esse formato não existe!");
        }
    }

    public String dataPorExtenso() {
        String[] meses = {"janeiro", "fevereiro", "março", "abril", "maio", "junho"
        ,"julho", "agosto", "setembro", "outubro", "novembro", "dezembro"};
     
        return String.valueOf(dia) + " de " + meses[mes - 1] + " de " + String.valueOf(ano);
    }
 
    public double qtdeDeDias(MinhaData data1, MinhaData data2) {
     
        int[] nroDiasMes = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int dias = 0;
 
        for(int i=0; i<data1.ano; i++) {
            if(anoBissexto(i)) {
                dias += 366;
            } else {
                dias += 365;
            }
        }
     
        for(int i=0; i<data1.mes; i++) {
            dias += nroDiasMes[i];
        }
     
        for(int i=0; i<data1.dia; i++) {
            dias += 1;
        }
     
        for(int i=0; i<data2.ano; i++) {
            if(anoBissexto(i)) {
                dias -= 366;
            } else {
                dias -= 365;
            }
        }
     
        for(int i=0; i<data2.mes; i++) {
            dias -= nroDiasMes[i];
        }
     
        for(int i=0; i<data2.dia; i++) {
            dias -= 1;
        }
     
     
        return Math.abs(dias);
    }

}


MinhaString.java
package logica;

/**
 *
 * @author guilherme
 */
public class MinhaString {
    char[] str;

    public MinhaString(char[] str) {
        this.str = str;
    }
   
    public int tamanho(char[] str) {
        int tamanho = 0;
        for(char c : str) {
            ++tamanho;
        }
        return tamanho;
    }
 
    public char[] concatena(char[] str) {
        int tam = tamanho(str) + tamanho(this.str);
        char[] aux = new char[tam];
     
        for(int i = 0; i < tamanho(this.str); i++) {
            aux[i] = this.str[i];
        }
     
        for(int i = tamanho(this.str), j = 0; i < tam; i++, j++) {
            aux[i] = str[j];
        }
     
        this.str = aux;
     
        return this.str;
    }
 
    public char[] maiuscula() {
        char[] aux = str;
        for(int i=0; i < tamanho(aux); i++) {
            if(str[i] > 96 && str[i] < 123) {
                str[i] -=32;
            }
        }
        return this.str;
    }
 
    public char[] minuscula() {
        char[] aux = str;
        for(int i=0; i < tamanho(aux); i++) {
            if(str[i] > 64 && str[i] < 91) {
                str[i] +=32;
            }
        }
        return this.str;
    }
 
    public char[] inverte() {
        int tam = tamanho(str);
        char[] x = espelha(str);
        for(int i=tam-1, j=0; i > -1; i--, j++) {
            str[j] = x[i];
        }
        return this.str;
    }
 
    public char[] trocarCaracter(char caracterAntigo, char caracterNovo) {
        char[] aux = espelha(str);
        for(int i=0; i<tamanho(aux); i++) {
            if(str[i] == caracterAntigo) {
                str[i] = caracterNovo;
            }
        }
        return str;
    }
 
    public char[] subString(int x, int y) {
        int tam = tamanho(str);
        if( (x >= 0 && x <= tam) && (y >= 0 && y <= tam) ) {
         
            char[] aux = new char[y - x];
         
            for(int i=x, j=0; i<y; i++, j++) {
                aux[j] = this.str[i];
            }
         
            return aux;
        }
        return this.str;
    }
 
    public int comparar(char[] str1, char[] str2) {
        /*
         *  0  são iguais
         *  1  maior
         * -1  menor
         */
     
        int t1 = tamanho(str1);
        int t2 = tamanho(str2);
     
        if(t1 > t2) {return 1;} else if(t2 > t1) {return -1;}
        else {
            for(int i=0; i<t1; i++) {
                if(str1[i] > str2[i]) {
                    return 1;
                } else if(str2[i] > str1[i]) {
                    return -1;
                }
            }
            return 0;
        }
    }
 
    public void valueOf(char[] str) {
        for (char c : str) {
            System.out.print(c);
        }
    }
 
    private char[] espelha(char[] str) {
        int tam = tamanho(str);
        char[] x = new char[tam];
        for(int i=0; i<tamanho(str); i++) {
            x[i] = str[i];
        }
        return x;
    }
 
}
Bom pessoal postei para ajudar e não para copiar, a intenção é evolução e não regressão beleza!? Bons estudos!

MinhaData versão Python

Fala pessoal, estava de boa aqui em casa e resolvi programar um pouco em Python. Implementei a classe MinhaData que originalmente foi escrita em Java.
Quando executei descobri um agravante, o código em Java estava cortando o resultado quando as datas passadas eram muito distantes. Já em Python não tive esse problema e a execução do código também se mostrou mais rápida ... o que o Java fazia em x minutos Python fazia em x/2.
Vamos ver como ficou? Segue o código ai:

MinhaData.py
#-*- encoding: utf-8 -*- import timeit class MinhaData(): def __init__(self, dia, mes, ano): self.dia = dia self.mes = mes self.ano = ano def isBissexto(self, ano): if ano % 4 == 0 and (ano % 100 != 0 or ano % 400 == 0): return True return False def calcDias(self, d1, d2): return abs(self.qtdeDias(d1) - self.qtdeDias(d2)) def qtdeDias(self, data): nroDiasMes = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] dias = 0 for dia in range(1, data.dia+1): dias += 1 for mes in range(data.mes): dias += nroDiasMes[mes] for ano in range(1, data.ano+1): if self.isBissexto(ano): dias += 366 else: dias += 365 return dias if __name__ == '__main__': d1 = MinhaData(21,03,2013) d2 = MinhaData(21,03,1994) print('Intervalo de',d1.calcDias(d1, d2), 'dia(s)')

Pessoal estou preparando um post juntamente com o Guilherme Bueno onde comparamos o desempenho das linguagens de programação: Java, C/C++ e Python executando um mesmo algoritmo ... aguadem. Bons estudos!!!

terça-feira, 12 de março de 2013

Realizando leitura com System.in.read

Fala pessoal, hoje vou mostrar como realizar a leitura do teclado utilizando System.in.read(). Então teremos hoje mais um post dedicado aos programadores Java e ao pessoal que gosta de Java. Gostaria de alertar que a partir do Java 5 a leitura do teclado é feita com a classe Scanner do pacote java.util.Scanner.

Realizando leitura do teclado sem utilizar a classe Scanner

Como dito anteriormente nas versões anteriores da Java 5 a leitura do teclado exigia um certo esforço do programador. Antigamente o programador utilizava o método System.in.read() que retorna um InputStream bufferizado. Então o programador pegava este buffer retornado e convertia-o para caracter para que ele pudesse converte-lo para os demais formatos.

Exemplos práticos

Vou utilizar dois problemas apresentados na aula de POO do IFSP campus Araraquara curso ADS para ilustrar como é feita a leitura utilizando a classe System.in.read().
  1. Construa um programa Java que leia o ano de nascimento do usuário e calcule a idade do mesmo;
  2. Construa um programa Java que leia uma sigla para sexo (M/F) e depois apresente no console o sexo lido;
    Atenção: A leitura do teclado deve ser realizada com o método System.in.read();

SysRead2.java
import java.io.IOException; public class SysRead2 { public static void main(String[] args) throws IOException { byte[] aux = new byte[4]; System.out.println("Informe seu ano de nascimento: "); System.in.read(aux); int anoNascimento = Integer.parseInt(new String(aux, "UTF-8")); System.out.println("Idade: " + (2013 - anoNascimento)); } }

SysRead3.java
import java.io.*; public class SysRead3 { public static void main(String[] args) throws IOException { byte sexo; System.out.println("Informe o sexo M/F: "); sexo = (byte) System.in.read(); System.out.println("Sexo digitado: " + (char)sexo); } }

Dúvidas e sugestões deixem comentários, Bons estudos.

domingo, 3 de março de 2013

Porque não utilizar o DefaultTableModel

Olá pessoal, hoje vamos falar de TableModel e porque não devemos utilizar o DefaultTableModel em sua JTable.
Para que o leitor compreenda o assunto tratado é necessário que o mesmo tenha conhecimento dos princípios básicos de POO e que conheça o funcionamento do toolkit para construções gráficas swing.

Nem sempre o modelo pronto é o mais fácil

Muitas vezes quando estamos trabalhando com JTable não nos preocupamos em implementar o modelo da Table e simplemente utilizamos o modelo padrão (DefaultTableModel). O DefaultTableModel é um modelo padrão utilizado para que o programador possa adaptá-lo a suas necessidades. Mas nem sempre adaptar esse TableModel padrão é uma boa escolha, na maioria das vezes o DefaultTableModel deixará o desempenho da aplicação comprometido assim como a segurança da mesma.

A situação pode ficar ainda pior, vamos supor que você tenha feito um software a 3 anos atrás e nesse software você persistio as informações com JDBC, porém, agora você deseja migrar para um ORM de sua proferencia, por exemplo Hibernate. Você terá que percorrer linha por linha da JTable e mapear as informações para objetos e depois montar um List para então poder salvar os dados contidos em sua JTable.

Por esse e outros motivos a melhor solução seria a implementação de um TableModel para cada JTable de sua aplicação e abolir de vez o uso do DefaultTableModel.

Implementando um TableModel simples

Sempre quando procuramos ajuda na Internet o pessoal escracha o DefaultTableModel e manda a pessoa implementar um TableModel e se quer diz como a pessoa deve fazer.

Veja a implementação de um TableModel para sua JTable:


public class TableModelOrdemServico extends AbstractTableModel { private String[] colunas = new String[]{"Descrição", "Qtde"};//aqui vc coloca os nomes que iram aparecer na coluna de sua JTable, o número de colunas é igual ao número de elementos que contem no Array private Class[] classeColuna = new Class[]{String.class, Integer.class};//aqui vc coloca o tipo de dado que cada coluna armazena. Os tipos suportados são: Integer, Double, String e Object. private List linhas;//Cada elemento do List representa uma linha da JTable, então quando um novo elemento é adicionado na tabela ele também é adicionado no List. public TableModelOrdemServico() { linhas = new ArrayList<>(); } public TableModelOrdemServico(List listaDeItensDeVenda) { this(); linhas.addAll(listaDeItensDeVenda); } @Override public String getColumnName(int columnIndex) {//Retorna o nome da coluna return colunas[columnIndex]; } @Override public int getColumnCount() {//Retorna o número de colunas que seu modelo tem. Repare que o número de colunas é igual ou tamanho do Array. return colunas.length; } @Override public int getRowCount() {//Retorna o número de linhas que o modelo da tabela tem. Repare que o número de elementos corresponde ao número de linhas do modelo return linhas.size(); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) {//Retorna qual célula da tabela é editável, nesse exemplo nenhuma célula é editável return true; } @Override public Class getColumnClass(int columnIndex) {//Retorna a classe da coluna selecionada return classeColuna[columnIndex]; } @Override public Object getValueAt(int rowIndex, int columnIndex) {//Retorna o valor contido da célula OrdemServico o = linhas.get(rowIndex); switch(columnIndex) { case 0: return o.getDescricao(); case 1: return o.getQtde(); default: return null; } } @Override public void setValueAt(Object obj, int rowIndex, int columnIndex) {//Modifica/Atualiza o valor contido na célula. OrdemServico o = linhas.get(rowIndex); switch(columnIndex) { case 0: o.setDescricao(obj.toString()); break; case 1: o.setQtde(Integer.parseInt(obj.toString())); break; case 2: o.setQtde(Integer.parseInt(obj.toString())); break; } fireTableDataChanged(); } //Os métodos listados acima devem ser reescritos em cada classe que extenda AbstractTableModel (se vc não entende o que a palavra extends representa em Java leia sobre Herança aqui no Blog temos um POST explicando sobre o assunto). //Você ainda pode implementar quantos métodos forem necessários para sua aplicação

Espero que tenham gostado e até a próxima pessoal.

domingo, 27 de janeiro de 2013

Programando em Java - parte 15

Métodos e classes finais (final)

Você deve estar se lembrando do modificador final que é utilizado em variáveis quando desejamos que o valor seja o mesmo durante toda a execução do programa (constantes). Além de poder ser utilizado em variáveis podemos utilizar esse cara em métodos e classes.

Métodos

Métodos final não podem ser sobrescritos nas subclasses que implementam sua superclasse. Uma declaração do método final nunca pode mudar, sendo assim todas as subclasses utilizam a mesma implementação do método.

final void parar() { //lógica para parar o que você quiser }

Classes

Uma classe final não pode ser estendida. Esta é uma medida de segurança da linguagem Java que impede a criação de subclasses mal-intencionadas afim de driblar a segurança do sistema.

public final class Autor { //essa classe não pode ser superclasse }
Chegamos ao final de mais um assunto, espero que tenham gostado de aprender sobre classes e métodos finais. Até a próxima.

Programando em Java - parte 14

Classes abstratas

Já vimos que em Java podemos criar classes genéricas e estende-las criando classes mais especificas (herança). Também vimos que podemos modificar os comportamentos da classe padrão em cada classe especifica (polimorfismo). Na maioria das vezes a função da classe genérica é apenas fornecer um "modelo" para que as classe filhas implementem, sendo assim não seria necessária a instanciação dessa classe genérica.

Em Java podemos criar classes que não podem ser instanciadas. Dizemos que temos dois tipos de classe: concretas (podem ser instanciadas) e não concretas (não podem ser instanciadas). Para criar uma classe abstrata em Java utilizamos a palavra reservada abstract.

Uma classe abstrata pode conter métodos abstratos e métodos não abstratos, porém, uma classe que não é abstrata não pode conter nenhum método abstrato. Métodos abstratos não fornecem implementações.

A classe concreta que implementar a superclasse abstrata deve implementar os métodos abstratos da mesma. Construtores e métodos estáticos (static) não devem ser abstratos. O construtor não é herdado, portanto nunca seria sobrescrito. Métodos estáticos não podem ser reescritos portanto não faz sentido que o mesmo seja abstrato.

Exemplo:

Criação da classe abstrata Transporte.
public abstract class Transporte { String cor, int ano; abstract void parar(); }
Criação da classe Moto.
public class Moto extends Transporte { String cor, int ano; @Override void parar() { //lógica para parar a moto } }
Criação da classe Navio.
public class Navio extends Transporte { String cor, int ano; @Override void parar() { //lógica para parar o navio } }
Com isso garantimos que todas as classes que implementarem a classe Transporte implementaram o método parar. Bom com isso encerramos mais um conteúdo, até a próxima pessoal.

sexta-feira, 25 de janeiro de 2013

Python 3 - Leitura de dados com input()

Introdução

Olá pessoal, ultimamente venho estudando a linguagem de programação Python. Quando iniciei meus estudos o Python estava em sua versão 2.7. Nessa versão criei toda a minha base que tenho hoje de Python, porém, o Python foi atualizado para a versão 3. Nessa versão algumas funções foram modificadas consequentemente o modo de utilizá-las também. Hoje foi falar da função de capturar entradas do teclado.

Python 2

Na versão anterior (usada em vários sistemas) para se capturar entradas do teclado era necessário utilizar a função raw_input(). A função raw_input() retorna uma string que pode ser convertida em qualquer tipo númerico de Python. Exemplo:

nome = raw_input('Entre com o nome : ') idade = int(raw_input('Entre com a idade : ')
A primeira linha retorna uma string com o nome que o usuário digitou. A segunda linha retorna uma string com a idade digita e logo em seguida a função int() converte essa string para um valor número inteiro.

Python 3

Na versão 3 do Python a função raw_input() mudou de nome e passou a se chamar apenas input(). A ideia original na versão 3 do Python era que as funções input e raw_input() deixassem de existir. Se isso acontecesse uma simples ação de ler dados do teclado seria algo assim:

import sys print ('Entre com o nome : ') nome = sys.stdin.readline()
Muito mais trabalhoso não é mesmo!!! Portanto a escolha foi substituir raw_input() por input(). Veja como ficaria:

nome = input('Entre com o nome : ') idade = int(input('Entre com a idade : ')
Bom é isso ai galera, se você gosta de Python, Java e programação em geral continue acompanhando o blog. Deixe o seu comentário!!! Abs.

Métodos - Parâmetros com tamanho indefinido

Introdução

Olá pessoal, muitas vezes estamos construindo uma aplicação em que não sabemos exatamente quantos parâmetros de um mesmo tipo o método vai ter em sua chamada (quando ele for acionado). Para solucionarmos este problema poderiamos declarar um vetor do tipo que desejado e passá-lo como parâmetro, porém, em Java temos uma forma mais elegante de se passar um número de parâmetros indefinido para os métodos. Vejamos como podemos faze-lo.

Passando um número indefinido de parâmetros

Como dito anteriormente a linguagem Java suporta a passagem de um número indefinido de parâmetros. Para fazer isso basta utilizar três pontos ( ... ) após a declaração do tipo da variável e logo após dos três pontos colocar o nome da variável. Quando isso é o compilador cria um array contendo os valores que foram passados por parâmetro. Exemplo:

public class App { static void tabuadaDo2(int ... num) { for(int n : num) { System.out.println(n + " x 2 = " + n*2); } } public static void main(String[] args) { tabuadaDo2(2,3,4,5,6,7,8,9,10);//podemos chamar passando os valores 1 à 1 tabuadaDo2(new int[]{1,2,3,4,5,6,7,8,9,10}); } }

Só é permitida a inclusão de uma parametro indefinido por método, pois, o parametro indefinido deve estar no fim do método (ultimo a ser declarado).  Exemplo;

public class App { static void tabuadaDo2(int ... num, double ... numeros) {//não compila for(int n : num) { System.out.println(n + " x 2 = " + n*2); } } public static void main(String[] args) { tabuadaDo2(2,3,4,5,6,7,8,9,10);//podemos chamar passando os valores 1 à 1 int[] list = {2,3,4,5,6,7,8,9,10}; tabuadaDo2(list); } }

É importante ressaltar que apenas variaveis indefinidas tem que serem unicas! Portanto um parametro indefinido pode fazer parte de um metodo que tenha mais de uma variavel de parametro. Exemplo:

public class App { static void tabuadaDo2(double numeros, int ... num) { for(int n : num) { System.out.println(n + " * " + numeros + " = " + n*numeros); } } public static void main(String[] args) { tabuadaDo2(2,3,4,5,6,7,8,9,10);//podemos chamar passando os valores 1 à 1 tabuadaDo2(new int[]{9,73,4,67,1,0}); } }

Espero que tenham gostado pessoal, qualquer coisa deixem um comentário. Até mais!!!

quarta-feira, 23 de janeiro de 2013

Resolução dos exercícios de matrizes em Java

Exercício 1. Crie um programa Java que receba duas matrizes como entrada de dimensões N:M (importânte que sejam tamanhos genéricos usuário deve definir). Ao termino da leitura programa deve calcular a multiplicação entre essas matrizes.

package matriz; import java.util.Scanner; public class MultiplicacaoDeMatrizes { private static Scanner s; /** * @param args */ public static void main(String[] args) { //variáveis usadas para ler as dimensões que a matriz terá int n, m; s = new Scanner(System.in); System.out.println("Informe o número de linhas da primeira matriz"); n = s.nextInt(); System.out.println("Informe o número de colunas da primeira matriz"); m = s.nextInt(); //declaração da primeira matriz int[][] m1 = new int[n][m]; System.out.println("Informe o número de linhas da segunda matriz"); n = s.nextInt(); System.out.println("Informe o número de colunas da segunda matriz"); m = s.nextInt(); //declaração da segunda matriz int[][] m2 = new int[n][m]; /* * A multiplicação de matrizes só é possível se o número de colunas dem1 for igual ao número de linhas de m2 * * Exemplo de matrizes que são multiplicaveis entre si: * * m1 = 4x1 m2 = 1x4 * m1 = 2x2 m2 = 2x10 * * Exemplo de matrizes que NÃO são multiplicáveis entre si: * * m1 = 3x3 m2 = 4x1 * m1 = 2x8 m2 = 2x8 * * Então antes de multiplicarmos as matrizes propriamente ditas, devemos conferir se o número de colunas de m1 é igual ao número * de linhas de m2. * */ if (m1[0].length != m2.length) { //se número de colunas de m1 for diferente de número de linhas de m2 então não pode multiplicar System.out.println("As matrizes não são multiplicáveis entre si!!!"); System.exit(1); //aborta o programa retornando um erro } else { //caso contrário, se forem iguais ai podemos multiplicá-las //realizar o preenchimento das matrizes System.out.println("Preenchendo a primeira matriz!"); for(int i = 0; i < m1.length; i++) { for(int j = 0; j < m1[0].length; j++) { System.out.println("Informe um valor: "); m1[i][j] = s.nextInt(); } } System.out.println("Preenchendo a segunda matriz!"); for(int i = 0; i < m2.length; i++) { for(int j = 0; j < m2[0].length; j++) { System.out.println("Informe um valor: "); m2[i][j] = s.nextInt(); } } //devemos declarar uma terceira matriz que será o resultado da multiplicação entre as matrizes (produto das matrizes m1 x m2) int[][] m3 = new int[m1.length][m2[0].length]; //multiplicando as matrizes /* * Os 2 primeiros for's representados por i e j respectivamente serão responsáveis por controlar o índice da matriz m3. * Já o terceiro for 'k', é responsável por perconrrer todos os elementos da horizontal e vertical das duas matrizes. * * */ for (int i = 0; i < m1.length; i++) { for (int j = 0; j < m1.length; j++) { for (int k = 0; k < m2.length; k++) { m3[i][j] += (m1[i][k] * m2[k][j]); } } } //imprimindo a matriz gerada for(int i = 0; i < m3.length; i++) { for(int j = 0; j < m3.length; j++) { System.out.print(m3[i][j] + "\t"); } System.out.println(); } } } }
Exercício 2.(Desafio) Crie um programa Java que seja capaz de ler informações de N funcionários da Google, o programa deve armazenar: Nome (String), Apelido (String), Idade (int), código (int). Já sabemos que matrizes em Java são homogêneas portanto só conseguem guardar um tipo único de dados. O programa deve exibir os N funcionários em ordem crescente por idade.

package matriz; import java.util.Scanner; public class OrdenacaoDeMatrizes { private static Scanner s; /** * @param args */ public static void main(String[] args) { s = new Scanner(System.in); String[][] m1 = new String[3][2]; int[][] m2 = new int[3][2]; for(int i = 0; i < 3; i++) { System.out.println("Informe o nome do " + (i+1) + "º funcionário: "); m1[i][0] = s.next(); System.out.println("Informe o apelido do " + (i+1) + "º funcionário: "); m1[i][1] = s.next(); System.out.println("Informe o código do " + (i+1) + "º funcionário: "); m2[i][0] = s.nextInt(); System.out.println("Informe a idade do " + (i+1) + "º funcionário: "); m2[i][1] = s.nextInt(); } /* * Utilizando o método de ordenação Bubble Sort * */ for(int i = 0; i < 3; i++) { for(int j = i; j < 3; j++) { if(m2[i][1] > m2[j][1]) { //Se o próximo elemento for maior então devemos trocar de lugar com seu antecessor String nome, apelido; int codigo, idade; //armazenando o maior (guarda os valores do antecessor) nome = m1[i][0]; apelido = m1[i][1]; codigo = m2[i][0]; idade = m2[i][1]; //maior recebe o menor (antecessor recebe próximo) m1[i][0] = m1[j][0]; m1[i][1] = m1[j][1]; m2[i][0] = m2[j][0]; m2[i][1] = m2[j][1]; //menor recebe maior (próximo recebe seu valores guardados) m1[j][0] = nome; m1[j][1] = apelido; m2[j][0] = codigo; m2[j][1] = idade; } } } //exibindo os dados ordenados em ordem crescente por idade for(int i = 0; i < 3; i++) { System.out.println("Nome: " + m1[i][0]); System.out.println("Apelido: " + m1[i][1]); System.out.println("Código: " + m2[i][0]); System.out.println("Idade: " + m2[i][1]); System.out.println(); } } }

Matrizes em Java

Olá pessoal, estava dando uma olhada em minhas publicações e percebi que estava faltando explicar sobre matrizes na linguagem Java. Bom vamos lá então.
Dica: Antes de ler sobre Matrizes em Java leia esse post que fala sobre vetores (arrays unidimensionais).


Cotidiano com matriz

Matriz por definição é um array multidimensional, ou seja, um array de várias dimensões. Para aplicações em nível de softwares comerciais dificilmente você irá empregar o uso de mais de duas dimensões em um array. Para declarar um array de 2D (duas dimensões) em Java fazemos:

int[][] array2D = new int[2][2];

Nesse exemplo foi declarado um array de "quadrado" de duas linhas e duas colunas. Um array 2D pode ser de vários tipos: String, float, int, double, porém, ele deve ser heterogêneo não podendo armazenar dados de tipos diferentes. Se o array foi declarado do tipo String então suas linhas e colunas devem armazenar somente valores do tipo String.

A solução para armazenar dados de diferentes tipos em matrizes (arrays multidimensionais) é a criação de outras matrizes e fazer a leitura associadamente. Por exemplo, suponha que você tenha que armazenar o nome, endereço, idade e código de um contato. Sabendo que código e idade são tipos inteiros de dados (int) e que nome e endereço são tipos caracteres de dados (String) como armazenar essas informações? Veja:

String[][] caracteres = new String[4][2]; int[][] inteiros = new int[4][2]; caracteres[0][0] = nome; caracteres[0][0] = endereco; inteiros[0][0] = codigo; inteiros[0][1] = idade
Dessa forma conseguimos guardar dados referentes a um mesmo contato em diferentes matrizes de diferentes tipos de dados. Para acessar todas as informações de um determinado contato basta informamos o mesmo número de linha para as duas matrizes, isso retorna todas as informações referentes ao contato procurado.

Vamos imaginar agora que nossa matriz tenha um número muito grande de elementos e que acessar ela índice por índice seria uma tarefa árdua e muito trabalhosa. Para percorrer uma matriz podemos utilizar a estrutura de repetição for. Veja como fica:

for(int i = 0; i < 4; i++) {     for(int j = 0; j < 2; j++) {         System.out.println(caracteres[i][j]);         System.out.println(inteiros[i][j]);     } }

Bom tudo o que foi apresentado até agora resolve muito bem o seu problema quando você conhece previamente o tamanho que a matriz tem. Mas e se você não souber o tamanho do matriz?

Quando não sabemos o tamanho da matriz o código fica um pouco mais complexo, mais nada que chega a assustar. Em Java podemos declarar o array sem fornecer um tamanho para ele, veja:

int[][] inteiros;
O que fizemos acima foi dizer a JVM que teremos um Array de duas dimensões, porém, não construímos esse array ainda portanto ele não pode ser utilizado. Agora devemos obter o tamanho que nosso array deve ter para então criarmos e utilizarmos ele. Veja o exemplo:

int r = (int) (Math.random()*100); //gera um número aleatório entre 0 e 99 inteiros = new int[r][r];

Beleza e agora para percorrermos o array devemos utilizar o tamanho armazenado em r, ou podemos utilizar um método para descobrir qual é esse tamanho. Para descobrir quantas linhas e colunas uma array multidimensional tem utilizamos o método length, veja:

inteiros.length; //retonar o número de linhas
inteiros[0].length; //retorna o número de colunas

Agora veja como podemos percorrer a matriz utilizando o método length:

for(int i = 0; i < inteiros.length; i++) {     for(int j = 0; j < inteiros[i].length; j++) {         System.out.println(inteiros[i][j]);     } }

Lembrando que para exibir somente a linha ou coluna de uma matriz podemos deixar o número fixo no índice e usar o for para percorrer dinamicamente os demais índices do array, veja:

//exibindo todos os elementos da linha 0 for(int coluna = 0; coluna < inteiros[0].length; coluna++) {     System.out.println(inteiros[0][coluna]); }
//exibindo todos os elementos da coluna 1 for(int linha = 0; linha < inteiros.length; linha++) {     System.out.println(inteiros[linha][1]); }


Pessoal seguem dois desafios abaixo para tentarem solucionar, tentam solucionar e dúvidas postem comentários. Vou postar o link com a resolução dos exercícios mais tarde. Abraço a todos!

Dica: comentar código é uma boa prática de programação.

  1. Crie um programa Java que receba duas matrizes como entrada de dimensões N:M (importânte que sejam tamanhos genéricos, usuário deve definir). Ao termino da leitura programa deve calcular a multiplicação entre essas matrizes (produto de matrizes).
  2. (Desafio) Crie um programa Java que seja capaz de ler informações de N funcionários de uma empresa, o programa deve armazenar: Nome (String), Apelido (String), Idade (int), código (int). Já sabemos que matrizes em Java são homogêneas portanto só conseguem guardar um tipo único de dados. O programa deve exibir os dados dos N funcionários em ordem crescente por idade.

Novidade!!! Agora vamos ter canal no Youtube =D

Fala pessoal tudo beleza, estou sumido a correria está forte por aqui. Estou querendo dar um start em um projeto antigo que vem desde o temp...