apenas uma figura bonitinha

8.  Escrevendo seus Próprios Métodos

 

Como vimos, repetições e iteradores nos permitem fazer a mesma coisa (rodar o mesmo código) várias e várias vezes. Porém, algumas vezes queremos fazer a mesma coisa um monte de vezes, mas de lugares diferentes do programa. Por exemplo, vamos supor que estejamos escrevendo um programa de questionário para um estudante de psicologia. Levando em conta os estudantes de psicologia que eu conheço e os questionários que eles me forneceram, seria algo parecido com isto:

puts 'Olá, e obrigado pelo seu tempo para me ajudar'
puts 'com essa pesquisa. Minha pesquisa é sobre'
puts 'como as pessoas se sentem com comida'
puts 'mexicana. Apenas pense sobre comida mexicana'
puts 'e tente responder, honestamente, cada questão'
puts 'com "sim" ou "não". Minha pesquisa não tem'
puts 'nada a ver com quem molha a cama.'
puts

#  Nós fazemos as perguntas, mas ignoramos as respostas.

boaResposta = false
while (not boaResposta)
  puts 'Você gosta de comer tacos?'
  resposta = gets.chomp.downcase
  if (resposta == 'sim' or resposta == 'não')
    boaResposta = true
  else
    puts 'Por favor, responda com "sim" ou "não".'
  end
end

boaResposta = false
while (not boaResposta)
  puts 'Você gosta de comer burritos?'
  resposta = gets.chomp.downcase
  if (resposta == 'sim' or resposta == 'não')
    boaResposta = true
  else
    puts 'Por favor, responda com "sim" ou "não".'
  end
end

#  Porém, nós prestamos atenção *nesta* questão.
boaResposta = false
while (not boaResposta)
  puts 'Você faz xixi na cama?'
  resposta = gets.chomp.downcase
  if (resposta == 'sim' or resposta == 'não')
    boaResposta = true
    if resposta == 'sim'
      molhaCama = true
    else
      molhaCama = false
    end
  else
    puts 'Por favor, responda com "sim" ou "não".'
  end
end

boaResposta = false
while (not boaResposta)
  puts 'Você gosta de comer chimichangas?'
  resposta = gets.chomp.downcase
  if (resposta == 'sim' or resposta == 'não')
    boaResposta = true
  else
    puts 'Por favor, responda com "sim" ou "não".'
  end
end

puts 'Apenas mais algumas perguntas...'

boaResposta = false
while (not boaResposta)
  puts 'Você gosta de comer sopapillas?'
  resposta = gets.chomp.downcase
  if (resposta == 'sim' or resposta == 'não')
    boaResposta = true
  else
    puts 'Por favor, responda com "sim" ou "não".'
  end
end

#  Faça mais um monte de perguntas sobre comida
#  mexicana.

puts
puts 'QUESTIONÁRIO:'
puts 'Obrigado por dispender seu tempo ao nos ajudar'
puts 'com nossa pesquisa. Na verdade, essa pesquisa'
puts 'não tem nada a ver com comida mexicana.'
puts 'Mas é uma pesquisa sobre quem molha a cama.'
puts 'As comidas mexicanas estavam lá apenas para'
puts 'baixar sua guarda na esperança de fazer você'
puts 'responder mais honestamente. Obrigado novamente.'
puts
puts molhaCama
Olá, e obrigado pelo seu tempo para me ajudar
com essa pesquisa. Minha pesquisa é sobre
como as pessoas se sentem com comida
mexicana. Apenas pense sobre comida mexicana
e tente responder, honestamente, cada questão
com "sim" ou "não". Minha pesquisa não tem
nada a ver com quem molha a cama.

Você gosta de comer tacos?
sim
Você gosta de comer burritos?
sim
Você faz xixi na cama?
de jeito nenhum!
Por favor, responda com "sim" ou "não".
Você faz xixi na cama?
NÃO
Por favor, responda com "sim" ou "não".
Você faz xixi na cama?
sim
Você gosta de comer chimichangas?
sim
Apenas mais algumas perguntas...
Você gosta de comer sopapillas?
sim

QUESTIONÁRIO:
Obrigado por dispender seu tempo ao nos ajudar
com nossa pesquisa. Na verdade, essa pesquisa
não tem nada a ver com comida mexicana.
Mas é uma pesquisa sobre quem molha a cama.
As comidas mexicanas estavam lá apenas para
baixar sua guarda na esperança de fazer você
responder mais honestamente. Obrigado novamente.

true

Um programa lindo e longo, com um monte de repetição. (Todas as seções de código que giram em torno de questões sobre comida mexicana são idênticas, e a questão sobre xixi na cama é ligeiramente diferente.) Repetição é uma coisa ruim. Mas nós não podemos fazer um grande iterador, porque algumas vezes nós queremos fazer alguma coisa entre as questões. Em situações como essa, é melhor escrever um método. Veja como:

def digaMoo
  puts 'mooooooo...'
end

        

Ahn... Nosso programa não disse mooooooo.... Por que não? Porque nós não o mandamos fazer isso. Nós apenas dissemos como fazer para dizer mooooooo..., mas nós nunca o mandamos fazer isso. Vamos lá, outra tentativa:

def digaMoo
  puts 'mooooooo...'
end

digaMoo
digaMoo
puts 'coin-coin'
digaMoo
digaMoo
mooooooo...
mooooooo...
coin-coin
mooooooo...
mooooooo...

Ah! Muito melhor. (Para o caso de você não falar francês, havia um pato francês no meio do programa. Na França, os patos fazem "coin-coin").

Então, nós definimos o método digaMoo (Nomes de método, assim como nomes de variáveis, começam com uma letra minúscula. Há exceções, como + ou ==). Mas métodos não têm de sempre estar associados com objetos? Bem, sim, eles têm. E nesse caso (assim como com o puts e o gets), o método está associado apenas com o objeto representando o programa como um todo. No próximo capítulo nós vamos ver como adicionar métodos a outros objetos. Mas primeiro...

Parâmetros de Métodos

Você deve ter notado que se podemos chamar alguns métodos (como o gets, ou o to_s, ou o reverse...) apenas como um objeto. Porém, outros métodos (como o +, o -, o puts...) recebem parâmetros para dizer ao objeto o que fazer com o método. Por exemplo, você não diz apenas 5+, certo? Você está dizendo ao 5 para adicionar, mas você não está dizendo o que adicionar.

Para adicionar um parâmetro ao digaMoo (o número de mugidos, por exemplo), nós podemos fazer o seguinte:

def digaMoo numeroDeMoos
  puts 'mooooooo...'*numeroDeMoos
end

digaMoo 3
puts 'oink-oink'
digaMoo  #  Isso vai dar erro porque não foi passado nenhum parâmetro.
mooooooo...mooooooo...mooooooo...
oink-oink
#<ArgumentError: wrong number of arguments (0 for 1)>

numeroDeMoos é uma variável que aponta para o parâmetro que foi passado. Vou dizer mais uma vez, mas é um pouco confuso: numeroDeMoos é uma variável que aponta para o parâmetro que foi passado. Então, se eu digitar digaMoo 3, o parâmetro é o 3, e a variável numeroDeMoos aponta para 3.

Como você pode ver, agora o parâmetro é necessário. Afinal, o que o digaMoo deve fazer é multiplicar 'mooooooo' por um número. Mas por quanto, se você não disse? Seu computador não tem a menor idéia.

Se compararmos os objetos em Ruby aos substantivos em português, os métodos podem, da mesma forma, ser comparados aos verbos. Assim, você pode imaginar os parâmetros como advérbios (assim como em digaMoo, onde o parâmetro nos diz como a digaMoo agir) ou algumas vezes como objetos diretos (como em puts, onde o parâmetro é o que o puts irá imprimir).

Variáveis Locais

No programa a seguir, há duas variáveis:

def dobreEste num
  numVezes2 = num*2
  puts 'O dobro de '+num.to_s+' é '+numVezes2.to_s
end

dobreEste 44
O dobro de 44 é 88

As variáveis são num e numVezes2. Ambas estão localizadas dentro do método dobreEste. Estas (e todas as outras variáveis que você viu até agora) são variáveis locais. Isso significa que elas vivem dentro do método e não podem sair. Se você tentar, você terá um erro:

def dobreEste num
  numVezes2 = num*2
  puts 'O dobro de '+num.to_s+' é '+numVezes2.to_s
end

dobreEste 44
puts numVezes2.to_s
O dobro de 44 é 88
#<NameError: undefined local variable or method `numVezes2' for #<StringIO:0x7f2702d70048>>

Variável local não definida... Na verdade, nós definimos aquela variável local, mas ela não é local em relação ao local onde tentamos usá-la; ela é local ao método.

Isso pode parecer inconveniente, mas é muito bom. Enquanto você não tiver acesso a variáveis de dentro dos métodos, isso também quer dizer que ninguém tem acesso às suas variáveis, e isso quer dizer que ninguém pode fazer algo como isso:

def pequenaPeste var
  var = nil
  puts 'HAHA! Eu acabei com a sua variável!'
end

var = 'Você não pode tocar na minha variável!'
pequenaPeste var
puts var
HAHA! Eu acabei com a sua variável!
Você não pode tocar na minha variável!

Há, atualmente, duas variáveis naquele pequeno programa chamadas var: uma dentro do método pequenaPeste e uma fora dele. Quando você chamou pequenaPeste var, nós realmente passamos a string que estava em var para a outra, então as mesmas estavam apontando para a mesma string. Então, o método pequenaPeste apontou a sua var local para nil, mas isso não fez nada com a var de fora do método.

Retornando Valores

Você deve ter notado que alguns métodos devolvem alguma coisa quando você os chama. Por exemplo, o método gets retorna uma string (a string que você digitou), e o método + em 5+3, (que é, na verdade 5.+(3)) retorna 8. Os métodos aritméticos para números retornam números, e os métodos aritméticos para strings retornam strings.

É importante entender a diferença entre métodos retornando um valor para onde ele foi chamado, e o seu programa gerando uma saída para a sua tela, como o puts faz. Note que 5+3 retorna 8; ele não imprime 8 na tela.

Então, o que o puts retorna? Nós nunca nos importamos antes, mas vamos dar uma olhadinha agora:

valorRetorno = puts 'Este puts retornou:'
puts valorRetorno
Este puts retornou:
nil

O primeiro puts retornou nil. Apesar de não termos testado o segundo puts, ele fez a mesma coisa; puts sempre retorna um nil. Todo método tem que retornar alguma coisa, mesmo que seja apenas um nil.

Faça uma pausa e escreva um programa que encontre o que o método digaMoo retornou.

Você está surpreso? Bem, as coisas funcionam assim: o valor de retorno de um método é simplesmente a última linha avaliada do método. No caso do método digaMoo, isso quer dizer que ele retornou 'puts mooooooo...'*numeroDeMoos, que é um simples nil, já que puts sempre retorna um nil. Se nós quisermos que todos os nossos métodos retornem a string 'yellow submarine', nós apenas temos que colocar ela no fim deles:

def digaMoo numeroDeMoos
  puts 'mooooooo...'*numeroDeMoos
  'yellow submarine'
end

x = digaMoo 2
puts x
mooooooo...mooooooo...
yellow submarine

Agora vamos tentar aquela pesquisa de psicologia de novo, mas desta vez vamos escrever um método que faça a pergunta para nós. Ele vai precisar pegar a questão como um parâmetro e retornar true se a resposta foi sim e false se a resposta foi não (Mesmo que nós ignoremos a resposta na maioria das vezes, é uma boa idéia fazer o método retornar a resposta. Assim nós podemos usar isso para a questão sobre molhar a cama). Eu também vou dar uma resumida na saudação e no final, apenas para ficar mais fácil de ler:

def pergunte pergunta
  boaResposta = false
  while (not boaResposta)
    puts pergunta
    replica = gets.chomp.downcase
    
    if (replica == 'sim' or replica == 'não')
      boaResposta = true
      if replica == 'sim'
        resposta = true
      else
        resposta = false
      end
    else
      puts 'Por favor, responda com "sim" ou "não".'
    end
  end
  
  resposta #  É isso o que será retornado (true ou false).
end

puts 'Olá e obrigado por...'
puts

pergunte 'Você gosta de comer tacos?'          #  Nós ignoramos o valor de retorno desse método.
pergunte 'Você gosta de comer burritos?'
molhaCama = pergunte 'Você faz xixi na cama?'  #  Nós salvamos o retorno desse.
pergunte 'Você gosta de comer chimichangas?'
pergunte 'Você gosta de comer sopapillas?'
pergunte 'Você gosta de comer tamales?'
puts 'Apenas mais algumas perguntas...'
pergunte 'Você gosta de beber horchata?'
pergunte 'Você gosta de comer flautas?'

puts
puts 'QUESTIONÁRIO:'
puts 'Obrigado por...'
puts
puts molhaCama
Olá e obrigado por...

Você gosta de comer tacos?
sim
Você gosta de comer burritos?
sim
Você faz xixi na cama?
de jeito nenhum!
Por favor, responda com "sim" ou "não".
Você faz xixi na cama?
NÃO
Por favor, responda com "sim" ou "não".
Você faz xixi na cama?
sim
Você gosta de comer chimichangas?
sim
Você gosta de comer sopapillas?
sim
Você gosta de comer tamales?
sim
Apenas mais algumas perguntas...
Você gosta de beber horchata?
sim
Você gosta de comer flautas?
sim

QUESTIONÁRIO:
Obrigado por...

true

Nada mal, hein? Nós podemos adicionar mais perguntas (e adicionar mais perguntas é fácil agora), mas nosso programa continuará pequeno! Isso é um grande progresso — o sonho de todo programador preguiçoso.

Mais um Grande Exemplo

Eu acho que outro exemplo de método seria muito útil aqui. Vamos chamar esse de numeroPortugues. Esse método vai pegar um número, como o 22, e retorná-lo por extenso (nesse caso, a string vinte e dois). Por enquanto, vamos fazê-lo trabalhar apenas com inteiros entre 0 e 100.

(NOTA: Esse método usa um novo truque para retornar a partir de um método antes do fim usando a palavra-chave return, e introduz um novo conceito: elsif. Isso deve ficar mais claro no contexto, mostrando como as coisas funcionam).

def numeroPortugues numero
  #  Nós apenas queremos números entre 0 e 100.
  if numero < 0
    return 'Por favor, entre com um número maior ou igual a zero.'
  end
  if numero > 100
    return 'Por favor, entre com um número menor ou igual a 100.'
  end
  
  numExtenso = ''  #  Esta é a string que vamos retornar.
  
  #  "falta" é quanto do número ainda falta para escrevermos.
  #  "escrevendo" é a parte que estamos escrevendo agora.
  falta   = numero
  escrevendo = falta/100               #  Quantas centenas faltam escrever?
  falta   = falta - escrevendo*100     #  Subtraia essas centenas.
  
  if escrevendo > 0
    return 'cem'
  end
  
  escrevendo = falta/10              #  Quantas dezenas faltam escrever?
  falta  = falta - escrevendo*10     #  Subtraia essas dezenas.
  
  if escrevendo > 0
    if escrevendo == 1  #  Oh-oh...
      #  Já que não podemos escrever "dez e dois",
      #  vamos fazer algo especial aqui
      if falta == 0
        numExtenso = numExtenso + 'dez'
      elsif falta == 1
        numExtenso = numExtenso + 'onze'
      elsif falta == 2
        numExtenso = numExtenso + 'doze'
      elsif falta == 3
        numExtenso = numExtenso + 'treze'
      elsif falta == 4
        numExtenso = numExtenso + 'catorze'
      elsif falta == 5
        numExtenso = numExtenso + 'quinze'
      elsif falta == 6
        numExtenso = numExtenso + 'dezesseis'
      elsif falta == 7
        numExtenso = numExtenso + 'dezessete'
      elsif falta == 8
        numExtenso = numExtenso + 'dezoito'
      elsif falta == 9
        numExtenso = numExtenso + 'dezenove'
      end
      #  Já que já cuidamos das unidades,
      #  não temos mais nada a escrever.
      falta = 0
    elsif escrevendo == 2
      numExtenso = numExtenso + 'vinte'
    elsif escrevendo == 3
      numExtenso = numExtenso + 'trinta'
    elsif escrevendo == 4
      numExtenso = numExtenso + 'quarenta'
    elsif escrevendo == 5
      numExtenso = numExtenso + 'cinqüenta'
    elsif escrevendo == 6
      numExtenso = numExtenso + 'sessenta'
    elsif escrevendo == 7
      numExtenso = numExtenso + 'setenta'
    elsif escrevendo == 8
      numExtenso = numExtenso + 'oitenta'
    elsif escrevendo == 9
      numExtenso = numExtenso + 'noventa'
    end
    
    if falta > 0
      numExtenso = numExtenso + ' e '
    end
  end
  
  escrevendo = falta  #  Quantos ainda faltam a escrever?
  falta   = 0         #  Subtraia esses.
  
  if escrevendo > 0
    if escrevendo == 1
      numExtenso = numExtenso + 'um'
    elsif escrevendo == 2
      numExtenso = numExtenso + 'dois'
    elsif escrevendo == 3
      numExtenso = numExtenso + 'três'
    elsif escrevendo == 4
      numExtenso = numExtenso + 'quatro'
    elsif escrevendo == 5
      numExtenso = numExtenso + 'cinco'
    elsif escrevendo == 6
      numExtenso = numExtenso + 'seis'
    elsif escrevendo == 7
      numExtenso = numExtenso + 'sete'
    elsif escrevendo == 8
      numExtenso = numExtenso + 'oito'
    elsif escrevendo == 9
      numExtenso = numExtenso + 'nove'
    end
  end
  
  if numExtenso == ''
    #  A única forma de "numExtenso" estar vazia é
    #  se o "numero" for 0
    return 'zero'
  end
  
  #  Se chemagmos aqui, então temos um
  #  número entre 0 e 100, então precisamos
  #  apenas retornar o "numExtenso"
  numExtenso
end

puts numeroPortugues(  0)
puts numeroPortugues(  9)
puts numeroPortugues( 10)
puts numeroPortugues( 11)
puts numeroPortugues( 17)
puts numeroPortugues( 32)
puts numeroPortugues( 88)
puts numeroPortugues( 99)
puts numeroPortugues(100)
zero
nove
dez
onze
dezessete
trinta e dois
oitenta e oito
noventa e nove
cem

Bem, ainda há algumas coisas nesse programa que eu não gostei. Primeiro: há muita repetição. Segundo: esse programa não consegue lidar com números maiores do que 100. Terceiro: há muitos casos especiais, muitos retornos (return). Vamos usar alguns vetores e tentar dar uma limpada:

def numeroPortugues numero
  if numero < 0  #  Nada de números negativos.
    return 'Por favor, digite um número positivo.'
  end
  if numero == 0
    return 'zero'
  end
  
  #  Nada de casos especiais! Nada de retornos!
  
  numExtenso = ''  #  Esta é a string que vamos retornar.
  
  unidades     = ['um'  , 'dois', 'tres', 'quatro', 'cinco',
                  'seis', 'sete', 'oito', 'nove']
  dezenas      = ['dez'     ,   'vinte'   ,    'trinta' ,   'quarenta',    'cinqüenta',
                  'sessenta',   'sessenta',    'oitenta',   'noventa']
  especiais =    ['onze'     ,  'doze'    ,    'treze'  , 'catorze', 'quinze',
                  'dezesseis',  'dezesete',    'dezoito', 'dezenove']
  
  #  "falta" é quanto do número ainda falta escrever.
  #  "escrevendo" é a parte que estamos escrevendo agora.
  falta  = numero
  escrevendo = falta/100           #  Quantas centenas ainda faltam escrever?
  falta  = falta - escrevendo*100  #  Subtraia essas centenas.
  
  if escrevendo > 0
    #  Aqui está o truque sujo:
    centenas   = numeroPortugues escrevendo
    numExtenso = numExtenso + centenas + ' centos'
    #  Isso é chamado "recursão". O que nós fizemos?
    #  Eu disse para o método chamar a si mesmo, mas
    #  passando "escrevendo" como parâmetro, ao invés
    #  de "numero". Lembre-se de que "escrevendo" é
    #  (agora) o número de dezenas que nós estamos escrevendo.
    #  Depois de adicionarmos as "centenas" a "numExtenso",
    #  nós adicionamos a string " centos". Então, se nós
    #  chamamos numeroPortugues com 1999 (numero = 1999),
    #  agora escrevendo será 19, e "falta" deve ser 99.
    #  A coisa mais preguiçosa que fazemos aqui é
    #  mandar o método numeroPortugues escrever o número
    #  19 por extenso, e então adicionando "centos" ao
    #  fim e escrevendo "noventa e nove" ao que falta.
    #  Ficando, portanto, "dezenove centos e noventa e nove".
    
    if falta > 0
      #  Nós não escrevemos dois centosecinqüenta e um'...
      numExtenso = numExtenso + ' e '
    end
  end
  
  escrevendo = falta/10           #  Quantas dezenas faltam escrever?
  falta  = falta - escrevendo*10  #  Subtraia dessas dezenas.
  
  if escrevendo > 0
    if ((escrevendo == 1) and (falta > 0))
      #  Não podemos escrever "dez e dois", temos que escrever "doze",
      #  então vamos fazer uma exceção.
      numExtenso = numExtenso + especiais[falta-1]
      #  O "-1" aqui é porque especiais[3] é 'catorze', e não 'treze'.
      
      #  Já que cuidamos do dígito das unidades,
      #  não falta mais nada
      falta = 0
    else
      numExtenso = numExtenso + dezenas[escrevendo-1]
      #  E o "-1" aqui é porque dezenas[3] é 'quarenta', e não 'trinta'.
    end
    
    if falta > 0
      #  Como nós não escrevemos "sessentaequatro"...
      numExtenso = numExtenso + ' e '
    end
  end
  
  escrevendo = falta  #  Quantas unidades faltam ser escritas?
  falta  = 0          #  Subtraia elas.
  
  if escrevendo > 0
    numExtenso = numExtenso + unidades[escrevendo-1]
    #  Novamente: O "-1" aqui é porque unidades[3] é 'quatro', e não 'três'.
  end
  
  #  Agora podemos, simplesmente, retornar o nosso "numExtenso"...
  numExtenso
end

puts numeroPortugues(  0)
puts numeroPortugues(  9)
puts numeroPortugues( 10)
puts numeroPortugues( 11)
puts numeroPortugues( 17)
puts numeroPortugues( 32)
puts numeroPortugues( 88)
puts numeroPortugues( 99)
puts numeroPortugues(100)
puts numeroPortugues(101)
puts numeroPortugues(234)
puts numeroPortugues(3211)
puts numeroPortugues(999999)
puts numeroPortugues(1000000000000)
zero
nove
dez
onze
dezesete
trinta e dois
oitenta e oito
noventa e nove
um centos
um centos e um
dois centos e trinta e quatro
trinta e dois centos e onze
noventa e nove centos e noventa e nove centos e noventa e nove
um centos centos centos centos centos centos

Ahhhh.... Agora está muito melhor. O programa está um pouco maçante, mas é porque eu enchi de comentários. Agora ele funciona para números grandes... embora não de uma maneira muito elegante. Por exemplo, eu acho que 'um trilhão' seria muito mais elegante para o último número, ou mesmo 'um milhão milhão' (muito embora todas as três estejam corretas). Na verdade, você pode fazer isso agora...

Algumas Coisinhas para Tentar

• Melhore o método numeroPortugues. Primeiro, coloque os milhares. Ou seja, ele deve retornar 'um mil' ao inves de 'dez centos' e 'dez mil' ao invés de 'um centos centos'. Seria interessante retornar 'cem', 'duzentos' e etc. ao invés de 'um centos', 'dois centos' e etc. (muito embora ambas as formas estejam corretas).

• Melhore o método numeroPortugues um pouquinho mais. Coloque milhões agora, assim você conseguirá coisas como 'um milhão' ao invés de 'um mil mil'. Depois tente adicionar bilhões e trilhões. Quão longe você consegue ir?

"Um elefante incomoda muita gente..." Usando o método numeroPortugues, escreva esse clássico corretamente agora. Coloque seu computador de castigo: faça ele contar 9999 elefantes (Não exagere nos elefantes, porém. Escrever todos esses elefantes na sua tela vai demorar um pouco. Se você pensar em um milhão de elefantes, você vai acabar se colocando de castigo!).

Parabéns! Agora você já é um verdadeiro programador! Você aprendeu tudo o que você precisava para escrever grandes programas do zero. Se você tiver idéias de programas que você gostaria de escrever para você mesmo, tente agora!

Claro que escrever tudo do zero pode ser um processo muito lento. Por que gastar tempo e energia escrevendo um código que alguém já escreveu? Você quer um programa que mande alguns e-mails? Você gostaria de salvar e carregar arquivos em seu computador? Que tal gerar páginas da web para um tutorial onde os exemplos de código sejam executados cada vez que a página é carregada? :) Ruby tem muitos tipos diferentes de objetos que podemos usar para nos ajudar a escrever programas mais rapidamente.

 

© 2003-2014 Chris Pine