Mostrando postagens com marcador Algoritmo/Portugol. Mostrar todas as postagens
Mostrando postagens com marcador Algoritmo/Portugol. Mostrar todas as postagens

domingo, 2 de junho de 2013

Funções em Python - Variáveis por referência ou valor?

Olá pessoal, hoje vamos aprender um pouco mais de Python e entender como essa linguagem trabalha com variáveis em chamadas de funções.

Quando estamos escrevendo um programa estruturado certamente iremos construir algumas funções para solucionar algum problema. Em muitas linguagens de programação temos a opção de passar valores por refência ou por valor.

Quando passamos valores por referência estamos na verdade passando o endereço de memória onde a variável original aponta, então quem recebe esse endereço tem o que chamamos de acesso direto e toda alteração feita localmente reflete a variável original uma vez que o endereço apontado pela variável local é o mesmo da original.

Quando passamos por valor a variável local recebe uma "cópia" do valor que a variável original armazena, e toda a mudança que a variável local recebe NÃO é refletida na variável original pois a variável local é apenas uma cópia de seu valor.

Em Python não fazemos essa divisão em valor ou referencia. Em Python tudo é objeto, e quando eu digo tudo é tudo mesmo: 1, 10, 45, 543,  *lista, *tuplas, *dicionários, etc.

Então como fazer essa divisão em Python? Ora, muito simples. Dizemos que temos objetos que são mutáveis e objetos que são imutáveis. Objetos mutáveis como o próprio nome diz são objetos que podem mudar no decorrer da interpretação do código e objetos imutáveis são aqueles que não mudam no decorrer do código. Exemplo de objetos imutáveis: 1, 20, 123. O objeto 1 quando iniciamos o programa é 1 e no final dele continua sendo 1.

Agora objetos que são mutáveis temos: *listas, *dicionário, etc. Uma lista pode começar fazia, e no final da interpretação terminar com 10 elementos.

* Estruturas de dados da linguagem Python.

Persistir mudanças em variáveis externas

E agora vem a pergunta: Como fazer uma variável externa recuperar o valor que foi dado à ela dentro de uma função?.

A primeira coisa a ver nesse caso é se a variável a ser passada é mutável ou imutável. Caso ela seja mutável não é preciso fazer nada, toda a mudança que ela receber na função vai ser refletida a variável original .
def adicionarItem(item, lista): lista.append(item) lista = list() adicionarItem(5, lista) adicionarItem(10, lista) print(lista)
Veja que criamos uma lista, onde valores são inseridos e ao final exibimos e comprovamos que os valores foram inseridos na lista. Agora se a variável for imutável devemos retornar o valor calculado dentro da função para a variável externa, fazendo com que ela receba esse valor. Exemplo:
def incrementar(a): a += 1 return a a = 5 a = incrementar(a) print(a)
Temos uma função cujo o seu propósito é incrementar um ao valor original da variável passada. Criamos uma variável com o valor 5 e logo em seguida estamos chamando a função e atribuindo o valor de retorno a nossa variável. Ao final estamos imprimindo o valor calculado pela nossa função. Nesse caso nada de errado aconteceu e o valor 6 foi mostrado como já era previsto. Mas e se não tivéssemos atribuído esse retorno a variável, será que o resultado seria o mesmo? Vamos testar:
def incrementar(a): a += 1 return a a = 5 incrementar(a) print(a)
Opa agora o resultado que foi mostrado na tela foi o número 5 :s!!! Isso não era para estar acontecendo! Na verdade era, em Python temos uma tabela de objetos onde cada objeto tem um ID. Então quando criamos uma variável ela é uma etiqueta para esse ID que por sua vez faz uma referencia a memória. Então quando a variável é criada ela está etiquetando o ID do Objeto 5, é criada uma outra variável só que localmente e essa aponta para ID 6. Como a variável local não é retornada ela morre ou melhor deixa de existir assim que a função acaba de ser interpretada. Bom pessoal por hoje é só espero que tenham gostado. Bons estudos!!!

Estruturas em C - struct (só o básico)

Olá pessoal, hoje vamos falar de struct (Estruturas). As estruturas existem em linguagem C para agrupar dados de diferentes tipos. Podemos definir estruturas como tipo de dados  que armazenam dados de tipos desiguais.

Nota: Podemos imaginar estruturas como sendo matrizes, porém, ela seria uma matriz turbinada que pode armazenar mais de um tipo de dado.

Criando uma estrutura

Para criar uma estrutura usamos a palavra-chave struct. Quando fazemos isso estamos definindo para o compilador um novo tipo de dado. Exemplo:

struct Relogio { int horas; int minutos; int segundos; };
A definição de uma estrutura não cria nenhuma variável, somente informa ao compilador as características de um novo tipo de dado. A palavra struct indica que um novo tipo de dados está sendo definido e Relogio será a sua entiqueta.

Outra coisa importante a dizer é que nesse exemplo definimos a struct como sendo global, ou seja, ela está acessível em qualquer parte do código. Podemos definir nossa struct dentro de uma função, com isso ela só poderá ser utilizada dentro dessa função pois seu escopo será local e não mais global. Exemplo:

#include <stdio.h>  int main(void) { struct Relogio { int horas; int minutos; int segundos; }; struct Relogio r; printf("\n O ponteiro hora está parado em qual número? \n >>> "); scanf("%d", &r.horas); printf("\n O ponteiro minuto está parado em qual número? \n >>> "); scanf("%d", &r.minutos); printf("\n O ponteiro de segundo está parado em qual número? \n >>> "); scanf("%d", &r.segundos); /* Não estou considerando se a hora é inválida! */ printf("\n Hora lida \n >>> %d:%d:%d", r.horas, r.minutos, r.segundos); return 0; }
No exemplo acima Relogio só pode ser acessado dentro da função principal (main). Por fim dessa introdução ao assunto gostaria de deixar uma definição sobre estruturas:
Uma estrutura é um tipo de dado cujo formato é definido pelo programador.

typedef + struct

Em C temos um recurso para dar novos nomes a tipos de dados que já existem (typedef). Com ele podemos então nomear as nossas estruturas. Podemos utilizar ele de 3 distintas formas, porém, para ser mas breve o possível vou adotar apenas uma forma e levar até o fim desse post.

typedef struct { int horas; int minutos; int segundos; } Relogio; Relogio rolex; /*Declara uma variavel do tipo Relogio*/
Para acessar os membros contidos em nossa struct utilizamos o operador "." (ponto final).
rolex.horas = 1;
Para acessar os membros de uma struct devemos utilizar o operador ponto. Esse operador conecta o nome de uma variável estrutura ao membro dela.

Estruturas aninhadas

Podemos ter uma estrutura que contém outra estrutura. Quando isso ocorre damos o nome de estruturas aninhadas. Para criar uma estrutura aninhada devemos criar todas as estruturas que agregam/compõem outras estruturas afim de suprir essa hierarquia montada:

typedef struct { int notas[3]; } Boletim; typedef struct { char nome[30]; Boletim boletim; } Aluno;
No exemplo acima temos duas estruturas: Boletim e Aluno. A estrutura Boletim possui apenas um membro já a estrutura Aluno possui dois membros, inclusive um de seus membros é do tipo Boletim. Então devido essa dependência devemos definir primeiramente Boletim e depois Aluno.
Para utilizar estruturas contidas em outras estruturas a ideia é a mesma. Devemos acessar os níveis hierárquicos utilizando o operador ponto e depois fazer a atribuição do valor, ou recuperar o mesmo. Exemplo:

typedef struct { int notas[3]; } Boletim; typedef struct { char nome[30]; Boletim boletim; } Aluno; Aluno Guilherme; int main(void) { Guilherme.boletim.notas[i]=10; return 0; }
Pessoal escrevi só o basicão, caso você goste e se interessou pelo assunto deixe seu comentário pedindo uma segunda parte mais avançada que eu farei ... lembre-se só farei se a demanda for alta por isso ajude ai compartilhando. Bons estudos!

domingo, 21 de abril de 2013

Manipulando arquivos XML em Python

Fala pessoal hoje vamos aprender como escrever e ler arquivos XML utilizando a linguagem de programação Python.

Na maioria da vezes temos que salvar informações que os usuários ou sistemas geram. Podemos salvar essas informações de várias formas , seja em um banco de dados, em arquivos de texto, na nuvem, etc. Eu diria que a mais tradicional de todas elas seria salvar em um bom banco de dados como (MySQL, PostgreSQL, Oracle) mas em determinadas aplicações o seu uso é desnecessário ou até mesmo inaplicável. Quando isso ocorre devemos então salvar as informações em arquivos de texto, porém, os arquivos de texto não são lá muito elegantes e legíveis.

Eis então que surge os arquivos XML que podemos definir a grosso modo como sendo arquivos de texto estruturados. O XML é muito utilizado hoje para garantir que dois sistemas possam se interagir normalmente. Um bom exemplo seria o sistema de emissão de nota fiscal online onde a troca de informações entre o sistema proprietário e o sistema da receita federal é toda feita através de arquivos no formato XML.

Escrevendo em formato XML

Para escrever em formato XML utilizando Python podemos utilizar a biblioteca ElementTree que já vem nos pacotes de instalação do interpretador Python.

Para utilizar essa biblioteca primeiramente devemos importa-la :
from xml.etree.ElementTree import Element, ElementTree
Feito isso já podemos utilizar todos os recursos de nossa biblioteca. Todo arquivo XML possui o que podemos chamar de Nó Pai ou simplesmente de root e a partir dele vários desmenbramentos que podem ou não ter filhos e assim sucessivamente. Para criar um root fazemos:
root = Element('Agenda')
Agora a partir do root criamos os sub-nos ou filhos de root:

pessoa = Element('Pessoa') cliente = Element('Cliente', nome='Guilherme', idade='19', peso='71', altura='1.63')
Acima criamos dois filhos de agenda, um chamado pessoa e o outro chamado cliente. Como podemos ver pessoa não possui nenhum atributo enquanto o cliente possui 4 atributos: nome, idade, peso, altura. Quando uma tag não possui atributos dizemos que ela é vazia esse é o caso da tag pessoa.

Ainda temos que dar o comando de escrita, ou seja, o comando que vai criar o nosso arquivo XML. Senão fizermos isso ao final da execução programa não teremos um arquivo gerado. Para gerar/escrever um arquivo XML devemos fazer:

root.append(pessoa) root.append(cliente) ElementTree(root).write('agenda.xml');
Perceba que o comando append foi utilizado em root, isso indica que na estrutura root estamos adicionando duas outras estruturas filhas chamadas sucessivamente de pessoa e cliente. Logo após utilizamos o comando write onde passamos o nome do arquivo que será gerado, caso o arquivo exista o mesmo será atualizado caso contrário um novo arquivo será gerado com o nome que foi passado como argumento.

O nosso arquivo XML tem essa seguinte estrutura:

<Agenda> <Pessoa /> <Cliente altura="1.63" idade="19" nome="Guilherme" peso="71" /> </Agenda>

Lendo arquivos no formato XML

Como já sabemos um arquivo XML tem um Nó (node, raíz). Através desse nó principal podemos descobrir e listar os demais nós presentes em nossa estrutura. Vimos que cada nó contido no root nomeamos de filhos ou sub-nós.

Vejamos como abrir um arquivo XML utilizando o ElementTree:

tree = ElementTree(file='agenda.xml')
Após abrir o arquivo devemos então recuperar o elemento root para então recuperar os seus filhos. Para recuperar o elemento root de um arquivo XML fazemos:
r = tree.getroot()
Agora sabemos que r contém o nó root da nossa árvore XML. Portanto para recuperar os outros nós basta percorrer todos os filhos de root. Para percorrer os filhos de um nó utilizamos:
pessoa = r.find('Pessoa') cliente = r.find('Cliente')
Pronto agora os nós estão armazenados em variáveis possibilitando assim a manipulação. Você pode imprimir tags ou atributos utilizando essa biblioteca, veja como é simples:
print (cliente.tag, cliente.attrib)
Muito simples trabalhar com a linguagem Python não é mesmo? Abaixo segue o código completo para que você possa analisar parte a parte. Um abraço a todos e bons estudos!!! from xml.etree.ElementTree import Element, ElementTree """ Escrevendo os dados em formato XML e gerando o arquivo """ # Criando o nó superior "root" root = Element('Agenda') pessoa = Element('Pessoa') cliente = Element('Cliente', nome='Guilherme', idade='19', peso='71', altura='1.63') root.append(pessoa) root.append(cliente) ElementTree(root).write('agenda.xml'); """ Lendo o arquivo XML que foi persistido pela primeira parte do código """ tree = ElementTree(file='agenda.xml') r = tree.getroot() # Lista os elementos abaixo do root print (r.getchildren()) # Encontra a pessoa pessoa = r.find('Pessoa') # Encontra o cliente cliente = r.find('Cliente') print (cliente.tag, cliente.attrib)

terça-feira, 16 de abril de 2013

Erros comuns que acontecem com iReport




Olá pessoal, hoje vou falar de uma experiência desagradável que tive na minha vida. Vou falar do polêmico iReport. 

O iReport é uma ferramenta para construção de relatórios em vários formatos, tais como: HTML, XLS e PDF. O iReport pode ser utilizado com a linguagem de programação Java ou PHP.

Sem dúvidas o iRepot é uma excelente ferramenta no que se diz respeito à criação de relatórios, porém, seu uso pode acarretar uma experiência não muito agradável. Recentemente utilizei o iReport em um projeto onde tive que criar desde relatórios simples a relatórios mais elaborados. Tive vários probleminhas que tive que descobrir com ajuda de alguns gurus Java e outros que tive que descobrir na raça mesmo.

Por esse motivo fiz um compilado dos problemas que tive na hora de gerar meus relatórios.

  1. Versões diferentes
  2. Fontes diferentes
  3. Gerar .jar 

Versões diferentes

O iReport possui várias versões e nenhuma delas são compatíveis entre si. Se você construir um relatório utilizando a versão 3 e no seu projeto você está utilizando a biblioteca da versão 4 o relatório não irá rodar. O que é no minimo estranho já que sua biblioteca é de uma versão superior a do seu relatório. 

Mas o maior problema não é quando o relatório não roda, o problema começa quando você debuga para achar o erro. Quando você debuga o seu projeto o mesmo diz que não tem nenhum erro e passa normalmente o código, deixando o programador muito confuso já que erros não foram detectados e mesmo assim o seu relatório não abre.

Então se você está desenvolvendo aplicações com iReport e seu relatório não está abrindo fique atento provavelmente a versão do iReport que você incluiu no diretório libs de seu projeto não é a mesma versão do iReport em que o arquivo foi desenhado. 

Fontes diferentes

Parece brincadeira de mal gosto mas é isso mesmo, se seu relatório contem fontes que não estejam instaladas no sistema operacional do cliente ele se quer irá abrir ou muito menos dar uma mensagem de erro. Isso acontece também pelo fato do iReport ser na minha opinião um pouco "ingenuo", ora se a fonte não está instalada no cliente apresente uma fonte padrão da mesma família da fonte não instalada, por exemplo: sans-serif, serif, courier, etc.

Uma dica de quem já quebrou a cabeça com isso. Use somente fontes que você tenha certeza que estejam instaladas no cliente, ou use fontes que sejam genéricas como: sans-serif, serif, etc.

Gerar .jar

Esse é um problema muito frequente em qualquer tipo de aplicação, mas quando você utiliza o iReport ele pode ficar um pouco mais chatinho de resolver. O jar é o executável de um programa Java então todos os arquivos de seu programa estão contidos no jar. Caso você não inclua os arquivos em seu .jar o mesmo não irá executar na máquina cliente ... mesmo se você instalar o iReport na máquina do cliente.

Parece coisa de boçal essa dica mas programadores .NET irão gostar,  pois o Crystal Reports você não libera ele com a aplicação você deve instalá-lo na máquina do cliente.

Bom pessoal por hoje é só e nos vemos no próximo post. Bons estudos!!!

domingo, 14 de abril de 2013

Número arbitrário de argumentos em funções

Fala pessoal, hoje vou mostrar como trabalhar com números de argumentos arbitrários em funções.  Muitas vezes temos que fazer um código onde não sabemos quantos argumentos serão passados quando o código estiver em execução.

Em Python podemos receber tipos arbitrários de funções de duas formas. A primeira seria usando tupla e a segunda usando dicionario.

Relembrando conceitos

Tuplas são listas de dados imutáveis. Quando o programa está em execução não podemos modificar os valores contidos nos índices da tupla, ou seja, se no inicio do programa a posição 1 da tupla armazena o dado 'programado' até o final do programa a posição 1 irá armazenar esse dado.

Dicionários são listas de dados que combinam par de chave valor, ou seja, invés de associarmos indices com dados no dicionário adicionamos chaves com dados. Por exemplo:

programador = 'Guilherme'
(chave)         (dado)

E para recuperarmos o dado devemos informar o nome da chave.

Simples não é mesmo? Bom vamos voltar para a ideia central do post.

Trabalhando com N parâmetros na chamada da função

Bom primeiramente vamos imaginar o seguinte cenário: "Elabore um programa que realize a somatória de N números inteiros e exiba o valor calculado". 

Sabemos que vamos trabalhar com muitos parâmetros, porém, não nos foi informado quantos. Sabemos também que são números inteiros ou seja entre dicionários e tuplas qual devemos escolher? Se você falou tuplas acertou.

Para identificar que um parâmetro é uma tupla basta  adicionar * antes de seu nome. Veja:

def funcao (*args):     pass
Com isso definimos uma tupla com o nome de args. Para chamar essa função basta colocar o seu nome e adicionar os números que deseja somar:

funcao (1,2,3,4,5,6,7,8,9,10)

E para compilar você deve colocar o comando python e logo após o nome do seu arquivo. Veja:

>> python arquivo.py

O que apareceu na sua tela? Exatamente nada rsrsrs!! Calma pequeno gafanhoto isso aconteceu porque não implementamos a somatória dos números. Vamos fazer isso então.

Para percorrer todos os valores de uma tupla podemos usar o comando for, que serve para percorrer um tipo de dado que seja Iterator. E por definição uma tupla é iterável. Para somar todos os dados da tupla devemos fazer:
soma = 0 for nro in args:     soma += nro return soma
Agora podemos chamar a função e imprimir o seu retorno:

print ( funcao(1,2,3,4,5,6,7,8,9,10)) >> 55
Viu como foi simples? Então o que fizemos foi o seguinte. Montamos uma estrutura for e varremos essa estrutura pegando os itens um a um e adicionamos os seus valores na variável local chamada soma. Ao final da função retornamos o valor de soma.
Veja o código completo:

arquivo.py

def funcao(*args): soma = 0 for nro in args: soma += nro return soma print (funcao(1,2,3,4,5,6,7,8,9,10))

Agora vamos trocar de cenário: "Elabora um programa que simule uma agenda telefonica. Onde o usuário deve informar o nome e o número do contato."

Bom acho que isso não podemos resolver com tuplas correto? Bem ainda nos resta o dicionário será que ele pode nos ajudar? Se você respondeu sim ... você acertou!

Para identificar que um parâmetro é um dicionário devemos adicionar ** antes de seu nome. Veja:

def funcao (**kwargs):     pass
Com isso definimos um dicionário com o nome de kwargs. Para chamar essa função basta colocar o seu nome e adicionar os nomes e seus respectivos números (contatos):

funcao(PHP=88888888, Python=77777777, Java=21212121, C=28826718)
Como você já sabe, se executarmos o nosso arquivo nada irá ocorrer pois nada foi implementado não é mesmo? Bom então lets programar pequeno gafanhoto.

Já sabemos que o for consegue percorrer objetos que sejam iteráveis, e adivinha só ... o dicionário é iterável o///. Então o nosso código ficará assim:
arquivo.py
def funcao(**kwargs): print ('Name \t Number ') for contato in kwargs: print ("\n{}\t{}".format(contato, kwargs[contato])) funcao(PHP=88888888, Python=77777777, Java=21212121, C=28826718)
Nossa muito fácil né pessoal nem parece que em poucas linhas de código já montamos uma agenda telefônica '-'. Sério pessoal, podemos pegar esse código e mandar ele salvar em um arquivo .txt e Ulalá teremos uma agenda *-*.

Porém você deve estar muito emocionado agora, sim eu sei que está kkk. Mas e se precisarmos de uma tupla, um dicionário e mais 3 parâmetros em uma mesma função será que isso é possível?

SIM É PLENAMENTE POSSÍVEL =). VEJA:

def funcao (arg1, arg2, arg3, *args, **kwargs):     pass
Cabe aqui uma dica. A tupla deve ficar antes do dicionário e o dicionário deve ser sempre o ultimo argumento.

Pessoal o post terminou :'( ... Bons estudos e até a próxima!!!

terça-feira, 9 de abril de 2013

Trabalhando com vários arquivos *.java

Fala pessoal, hoje vou mostrar como trabalhar com mais de um arquivo (.java) em seus projetos.

Introdução

Quando estamos aprendendo a programar geralmente escrevemos nossos códigos em um único arquivo. Isso é feito para que o aluno não se perca no decorrer de seu aprendizado e trabalhar com um único arquivo é muito mais simples do que trabalhar com vários.
Quando estamos programando no paradigma orientado a objetos muitas vezes (senão sempre) precisamos de mais que um arquivo. Programas grandes costumam possuir vários arquivos onde uma parte do código chama outro parte de código de um arquivo diferente.
Bom visto que para grandes programas temos que usar mais de um arquivo vamos então aprender como programar utilizando mais de um arquivo ... bora lá pé de pano?

Brincando com os arquivos

Vamos imaginar que temos o seguinte problema: Precisamos desenvolver um sistema para uma loja de jóias, essa loja deseja realizar o cadastro de produtos e clientes. Vamos deixar só isso por enquanto pequeno gafanhoto depois retomamos e brincamos mais ;-)

De acordo com o texto acima eu sei que vou ter no mínimo 3 arquivos não é mesmo? O primeiro arquivo seria para escrever código de manipulação de clientes, o segundo de produtos e o terceiro arquivo seria a minha classe principal.

Mais a questão é: "E se eu quiser fazer tudo no mesmo arquivo?". Na tem problema algum em codificar um programa inteiro em um único arquivo, vejamos por exemplo como criar as 3 classes de nosso programa em um único arquivo:


public class TestJoalheria { public static void main() { // CÓDIGO OCULTO } } public class Cliente { // CÓDIGO OCULTO } public class Produto { // CÓDIGO OCULTO }
Esse seria o nosso arquivo único com todas as classes que nosso sistema possui. Veja que não tem problema algum em ter todo o código em um único arquivo. A desvantagem em ter tudo programado em apenas um único arquivo seria a complexidade que o código ganharia. Imagine ter que procurar um erro em um arquivo que tenha 50 classes e o total de linhas seja igual à 100.000 linhas?!

Já que tratar tudo em um arquivo é algo muito complexo, imagine agora se o mesmo programa de 100.000 linhas estivesse divido em 50 arquivos diferentes. É muito mais fácil procurar um erro em um arquivo que você sabe que o erro está ali e esse arquivo tem agora 2000 linhas ... conseguiu enxergar a vantagem pequeno gafanhoto?

Bom vamos ver como ficou o código da Joalheria em vários arquivos? DICA: INCREMENTE FUNCIONALIDADES A MAIS NO SOFTWARE, SEI LÁ CONSTRUA UMA INTERFACE GRÁFICA ... OU DEIXE UM COMENTÁRIO DIZENDO O QUE GOSTARIA QUE EU MODIFICASSE NO CÓDIGO PARA TE AJUDAR MELHOR. BONS ESTUDOS. 

Cliente.java
public class Cliente { private String nome; private int idade; private String endereco; private String telefone; public Cliente(String nome, int idade, String endereco, String telefone) { this.nome = nome; this.idade = idade; this.endereco = endereco; this.telefone = telefone; } public String getNome() { return nome; } public int getIdade() { return idade; } public String getEndereco() { return endereco; } public String getTelefone() { return telefone; } }

Produto.java public class Produto { private String descricao; private float preco; private int estoque; public Produto(String descricao, float preco, int estoque) { this.descricao = descricao; this.preco = preco; this.estoque = estoque; } public String getDescricao() { return descricao; } public float getPreco() { return preco; } public int getEstoque() { return estoque; } }

Joalheria.java import java.util.List; import java.util.ArrayList; public class Joalheria { private List clientesCadastrados; private List produtosCadastrados; public Joalheria() { clientesCadastrados = new ArrayList<>(); produtosCadastrados = new ArrayList<>(); } public boolean adicionarCliente(Cliente cliente) { if (cliente != null) { clientesCadastrados.add(cliente); return true; } return false; } public boolean adicionarProduto(Produto produto) { if (produto != null) { produtosCadastrados.add(produto); return true; } return false; } public List getClientesCadastrados() { return clientesCadastrados; } public List getProdutosCadastrados() { return produtosCadastrados; } public int qtdeClientesCadastrados() { return clientesCadastrados.size(); } public int qtdeProdutosCadastrados() { return produtosCadastrados.size(); } }

TestJoalheria.java import javax.swing.JOptionPane; public class TestaJoalheria { Joalheria joalheria = new Joalheria(); private boolean cadastrarCliente(String nome, int idade, String endereco, String telefone) { return joalheria.adicionarCliente(new Cliente(nome, idade, endereco, telefone)); } private boolean cadastrarProduto(String descricao, float preco, int estoque) { return joalheria.adicionarProduto(new Produto(descricao, preco, estoque)); } private void imprimirClientes() { int qtde = joalheria.qtdeClientesCadastrados(); if (qtde > 0) { System.err.println("Número de clientes cadastrados na base de dados: " + qtde); for (Cliente c : joalheria.getClientesCadastrados()) { System.out.println("Nome: " + c.getNome()); System.out.println("Idade: " + c.getIdade()); System.out.println("Endereço: " + c.getEndereco()); System.out.println("Telefone: " + c.getTelefone()); System.out.println("------------------------------------"); } } else { System.err.println("Nenhum cliente encontrado!"); } } private void imprimirProdutos() { int qtde = joalheria.qtdeProdutosCadastrados(); if (qtde > 0) { System.err.println("Número de produtos cadastrados na base de dados: " + qtde); for (Produto p : joalheria.getProdutosCadastrados()) { System.out.println("Descrição: " + p.getDescricao()); System.out.println("Preço: " + p.getPreco()); System.out.println("Estoque: " + p.getEstoque()); System.out.println("------------------------------------"); } } else { System.err.println("Nenhum produto encontrado!"); } } // Esse cara nada mais é que o método que dá o ponta pé inicial public static void main(String[] args) { int opcao; TestaJoalheria test = new TestaJoalheria(); do { opcao = Integer.parseInt(JOptionPane.showInputDialog("Informe o que deseja cadastrar: \n1-Produtos\n2-Clientes\n\n0-Sair")); if (opcao == 1) { String descricao = JOptionPane.showInputDialog("Entre com a descrição do produto"); float preco = Float.parseFloat(JOptionPane.showInputDialog("Entre com o preço")); int estoque = Integer.parseInt(JOptionPane.showInputDialog("Entre com a quantidade em estoque")); if (!test.cadastrarProduto(descricao, preco, estoque)) { JOptionPane.showMessageDialog(null, "Erro ao cadastrar produto!"); } else { JOptionPane.showMessageDialog(null, "Produto cadasrtrado com sucesso!"); } } else if (opcao == 2) { String nome = JOptionPane.showInputDialog("Entre com o nome"); int idade = Integer.parseInt(JOptionPane.showInputDialog("Entre com a idade")); String endereco = JOptionPane.showInputDialog("Entre com o endereço"); String telefone = JOptionPane.showInputDialog("Entre com o telefone"); if (!test.cadastrarCliente(nome, idade, endereco, telefone)) { JOptionPane.showMessageDialog(null, "Erro ao cadastrar cliente!"); } else { JOptionPane.showMessageDialog(null, "Cliente cadasrtrado com sucesso!"); } } else { JOptionPane.showMessageDialog(null, "Sistema finalizado!!!"); } } while(opcao != 0); test.imprimirProdutos(); test.imprimirClientes(); } }

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.

domingo, 13 de janeiro de 2013

Praticidade em foco: Python + SQLite

Introdução

SQLite é uma biblioteca Open Source escrita em linguagem C, que implementa um interpretador SQL, e provê funcionalidades de banco de dados, usando arquivos, sem a necessidade de um processo servidor separado ou de configuração manual.

A vantagem mais significativa de usar o SQLite é a praticidade, principalmente no uso em aplicativos locais para desktops, aonde usar um SGBD convencional seria desnecessário e complicado de manter. (texto retirado do livro Python para desenvolvedores).

# -*- coding: utf-8 -*- import sqlite3 # Cria uma conexão e um cursor con = sqlite3.connect('contatos.db') cur = con.cursor() # Cria uma tabela sql = 'create table contatos '\ '(id integer primary key, '\ 'nome varchar(100), '\ 'email varchar(100))' cur.execute(sql) # sentença SQL para inserir registros sql = 'insert into contatos values (null, ?, ?)' # Dados recset = [('guilherme', 'gui@gui.com'), ('giovanna', 'gii@gii.com')] # Insere os registros for rec in recset: cur.execute(sql, rec) # Confirma a transação con.commit() # Seleciona todos os registros cur.execute('select * from contatos') # Recupera os resultados recset = cur.fetchall() # Mostra for rec in recset: print '%d: %s(%s)' % rec # Fecha a conexão con.close()

Esse é o jeito tradicional de se conectar a um banco de dados utilizando o Python puro. Também podemos utilizar ferramentas ORM para facilitar e agilizar nosso trabalho. Uma excelente ferramenta ORM para Python é a SQLAlchemy, em posts futuros abordarei mais sobre esse incrível framework.

Programando em Java - parte 13

Polimorfismo

Polimorfismo, é uma palavra de origem grega que siginifica "muitas formas". Em POO polimorfismo é a capacidade de objetos de classes diferentes responderem a mesma mensagem de diferentes maneiras.

Vejamos o seguinte exemplo:
Uma empresa de tecnologia resolveu desenvolver um controle universal que poderá controlar qualquer tipo de aparelho eletrônico, cada aparelho atende os comandos especificos definidos por ele. 

Segundo Jun Matsumoto (gerente da empresa) o controle remoto teria vários botões, sendo que todos eles seriam úteis para todos os aparelhos. Assim quando o usuáiro clicasse no botão ligar, todos os aparelhos que estivesse em um raio de 1,5m ligariam. 

Jun ainda acrescenta que cada aparelho se comportará de acordo com a sua função, ou seja, quando solicitamos via controle que os aparelhos liguem cada um ligara de acordo com as suas caracteríscas já que a geladeira liga de uma forma, o forno microondas de outra e assim em diante.
Repare que os aparelhos respondem ao mesmo sinal de formas diferentes, temos aqui um caso de POLIMORFISMO.


Tipos de polimorfismo

O polimorfismo pode ser classificado de 3 maneiras:
  1. Sobrecarga ( se você ainda não leu de uma paradinha e aproveite para esclarecer suas dúvidas)
  2. Sobreposição ( leia a seção Reecrita de Métodos, aproveite esse momento caso você não tenha lido )
  3. Inclusão
Vamos implementar o código e em seguida explicaremos o conceito de inclusão.

public class Aparelho { public void ligar () { System.out.println ("Ligar aparelho"); } }
public class TV extends Aparelho { public void ligar () { System.out.println ("Ascender tela"); } }
public void Torradeira extends Aparelho { public void ligar () { System.out.println ("Ascender luz on"); } }
public void Microondas extends Aparelho { public void ligar () { System.out.println ("Piscar luz de ativo"); } }
public class Controle { private Aparelho aparelho; public Controle (Aparelho aparelho) { this.aparelho = aparelho; } public void ligar () { aparelho.ligar (); } }
public class Principal { public static void main (String[] args) { Tv tv = new Tv ()/ Controle controle = new Controle (tv); controle.ligar (); } }

Polimorfismo de inclusão usa a capacidade de substituição da Herança, de uma classe mãe por qualquer classe descendente, para permitir um comportamento polimórfico nos métodos que usam a classe mãe.
No exemplo visto a cima,veja a classe Principal,  onde criamos um objeto do tipo TV e outro do tipo Controle, nós utilizamos o comportamento polimórfico do polimorfismo de inclusão. Fizemos isso quando substituímos a classe Aparelho (mãe) pela classe TV (filha) dentro da classe Controle. Assim, o atributo interno do tipo Aparelho da classe Controle pode receber qualquer objeto que seja de uma classe filha de Aparelho.

Arquivo de I/O em Python

Introdução

Escrever em arquivos é uma necessidade que muitas vezes você vai se deparar, seja para criar um arquivo de log ou mesmo para persistir as informações de seu sistema. A manipulação de arquivos em Python ocorre de uma maneira bem simples e tranquila, com apenas 2 linhas de código podemos criar e escrever ou ler um arquivo. 

Criando um arquivo em Python

O função open retorna um objeto de arquivo, e é frequentemente utilizada com dois argumentos: open (arquivo_nome, modo_operacao).

f = open ('arquivo.txt', 'w') f.close ()
O primeiro parâmetro é o nome do arquivo que será aberto, o segundo parâmetro é o modo de operação que esse arquivo será aberto:
  • w : Será aberto para edição (write). Quando um arquivo é aberto com 'w' todo os texto que o arquivo tinha antes de ser aberto é perdido.
  • r : Será aberto para leitura (read). Quando um arquivo é aberto com 'r' é possível acessar todo o seu conteudo para leitura, porém, nada pode ser inserido ou removido.
  • r + : abre o arquivo tanto para leitura quanto para escrita.
  • a : Funciona como o 'w', porém, não apaga o texto que havia no arquivo antes do mesmo ser aberto.

Leitura arquivos

Para ler o conteúdo de um arquivo utilizamos f.read (size), que lê todos os dados do arquivo e retornam esses dados como uma string. Se o parâmetro for omitido então todo os conteúdo do arquivo será carregado, caso contrário só será carregado o tamanho em bytes do valor passado por parâmetro. Se o fim do arquivo for atingido f.read () irá retornar um arquivo vazio.

Para ler uma única linha do arquivo utilizamos o comando f.readline (). Se f.readline () retornar uma linha vazia o arquivo acabou.

Também é possível retornar todas as linhas do arquivo com o comando f.readlines (), você ainda pode passar por parâmetro o valor em bytes que deseja carregar (ler) do arquivo. Se o valor for omitido todo o conteúdo do arquivo será omitido.

Ainda na leitura de arquivos podemos utilizar o comando for para realizar essa tarefa. Utilizá-lo é mais eficiente, rápido e resulta em código mais simples.

f = open ('notas.txt', 'r') for line in f: print line f.close ()

Escrita de arquivos

Para escrever algo em um arquivo podemos utilizar o comando f.write ('Guilherme Arthur de Carvalho'). Esse método escreve o conteúdo da string para o arquivo e retorna None.
Como o write só escreve objetos do tipo string, se desejar escrever algo que não seja string é necessário converter o valor para string. Lembrando que quando abrimos um arquivo no modo de operação w todo o conteúdo que existia antes no arquivo é apagado.

Se você deseja apenas adicionar texto para seu arquivo, ou seja, concatenar informações abra ele no modo de operação 'a'.

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...