Tutorial de RubyEust´quio “TaQ” Rangel (eustaquiorangel@yahoo.com)    a                19 de julho de 2005
Este trabalho est´ licenciado sob uma Licen¸a Creative Commons Atribui¸˜o-Uso N˜o-                 a                      ...
Sum´rio   a1 Introdu¸˜o         ca                                                                                        ...
4 Classes                                                                                                                 ...
12 XSLT                                                                                                                   ...
6
Um pouco de bate-papo . . .Eu comecei a fazer esse tutorial como sempre come¸o fazendo as minhas coisas: necessidade de me...
8
Cap´   ıtulo 1Introdu¸˜o       ca1.1     O que ´ Ruby              ePara explicar o que ´ Ruby, eu fa¸o uma tradu¸˜o livre...
ˆ Escrever extens˜es em C para Ruby ´ mais f´cil que em Perl ou Python, em grande parte por                    o          ...
Cap´   ıtulo 2Arrumando as coisas2.1     Preparando sua fonte de consultas´E sempre bom ter uma referˆncia das classes, m´...
¸˜         ATENCAO         Estou usando GNU/Linux durante todo esse tutorial, e presumo que voc^ est´ usando              ...
Cap´   ıtulo 3Conhecendo o b´sico da linguagem              a3.1     Vari´veis            aVamos destrinchar aqui alguns t...
retornado Fixnum, provando que o que o Matz disse na descri¸˜o do Ruby no come¸o desse tutorial ´                         ...
3.2        Tipos b´sicos                  a3.2.1       Blocos de c´digo                       oAntes de apresentar qualque...
usado o Bignum.Exemplos de ponto flutuante:     [taq@~]irb     irb(main):001:0>     f1 = 1.23     => 1.23     irb(main):002...
[taq@~]irb     irb(main):001:0>     s1 = "oi"     => "oi"     irb(main):002:0>     s2 = "oi, amigo!"     => "oi, amigo!"  ...
[taq@~]irb     irb(main):001:0>   my_nick = "TaQ"     => "TaQ"     irb(main):002:0>   my_nick_copy = my_nick.dup     => "T...
irb(main):003:0> s += " concatenado"     => "teste concatenado"     irb(main):004:0> s     => "teste concatenado"     irb(...
3.2.7    ArraysArrays podem conter v´rios tipos de objetos (ou n˜o):                     a                           a    ...
[taq@~]irb     irb(main):001:0> a = ["um","dois","tres"]     => ["um", "dois", "tres"]     irb(main):002:0> a.sort     => ...
Tamb´m podemos particionar um Array, usando o m´todo partition:    e                                          e     [taq@~...
Curioso com o teste, fui verificar a causa disso e descobri: ao contr´rio de Ruby (e ou-                                   ...
Express˜es regulares tamb´m podem ser criadas usando o construtor da classe ou %r:       o                 e     [taq@~]ir...
=> "06"     irb(main):007:0> mt[3]     => "2005"     irb(main):008:0> mt = er.match("20062005")     => nil     irb(main):0...
3.2.11    ProcsProcs s˜o blocos de c´digo associados ` uma vari´vel:       a             o                a         a     ...
[taq@~]irb     irb(main):001:0> def cinco_multiplos(n)     irb(main):002:1>    (1..5).map {|v| n*v}     irb(main):003:1> e...
parametro recebido:5     => [1, 2, 3, 4, 5]     irb(main):006:0>Os parˆmetros vari´veis vem na forma de um Array, e para i...
16     => nil     irb(main):007:0>Para converter uma Proc em um bloco de c´digo em um parˆmetro do m´todo, vocˆ pode usar ...
[taq@~]irb     irb(main):001:0>    s = "Oi, mundo!"     => "Oi, mundo!"     irb(main):002:0>    s.object_id     => -605086...
print   "Vamos verificar os objetos:n"     print   "s1 id:#{s1.object_id}, vale #{s1}n"     print   "s2 id:#{s2.object_id}...
Figura 3.1: Representa¸˜o de referˆncias aos objetos                                            ca          eVamos analisa...
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Próximos SlideShares
Carregando em…5
×

Apostila ruby-completa

3.906 visualizações

Publicada em

  • Seja o primeiro a comentar

Apostila ruby-completa

  1. 1. Tutorial de RubyEust´quio “TaQ” Rangel (eustaquiorangel@yahoo.com) a 19 de julho de 2005
  2. 2. Este trabalho est´ licenciado sob uma Licen¸a Creative Commons Atribui¸˜o-Uso N˜o- a c ca aComercial-Compatilhamento pela mesma licen¸a. cPara ver uma c´pia desta licen¸a, visite o chttp://creativecommons.org/licenses/by-nc-sa/2.5/br/ou envie uma carta paraCreative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. Este documento foi feito usando L TEX. A Vers˜o 0.1 a Para atualiza¸˜es, visite http://beam.to/taq/tutorialruby.php co A figura do logotipo de Ruby acima ´ de minha livre autoria, n˜o representando um e a logotipo oficial 2
  3. 3. Sum´rio a1 Introdu¸˜o ca 9 1.1 O que ´ Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 e 1.2 Onde encontro Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Arrumando as coisas 11 2.1 Preparando sua fonte de consultas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2 Preparando o ambiente de trabalho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Conhecendo o b´sico da linguagem a 13 3.1 Vari´veis . . . . . . . . . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.1.1 Escopo das vari´veis . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.2 Tipos b´sicos . . . . . . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.1 Blocos de c´digo . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.2 N´meros . . . . . . . . . . . . . . . u . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.3 Booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2.4 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2.5 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.2.6 Ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.2.7 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.2.8 Hashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.2.9 S´ ımbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.10 Express˜es regulares . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.11 Procs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.2.12 M´todos . . . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Retornando valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Recebendo parˆmetros . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Como os parˆmetros s˜o enviados a a . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 M´todos destrutivos . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 M´todos predicados . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 M´todos ou fun¸˜es . . . . . . . . e co . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.2.13 Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.2.14 Juntando tudo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.3 Estruturas de controle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.3.1 Condicionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 unless . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.3.2 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 until . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.4 Coment´rios no c´digo . . . . . . . . . . . a o . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3
  4. 4. 4 Classes 47 4.1 Vari´veis de instˆncia . . . . . . . . . a a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 4.2 Vari´veis de classe . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 4.3 M´todos de classe . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.4 Executando m´todos da classe pai . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.5 Redefinindo operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.6 Heran¸a . . . . . . . . . . . . . . . . . c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.7 Duplicando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.8 Controle de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.8.1 M´todos p´blicos . . . . . . . . e u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.8.2 M´todos privados . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 4.8.3 M´todos protegidos . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.8.4 Especificando o tipo de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 4.9 Classes e m´todos singleton . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715 Entrada e sa´ıda 73 5.1 Fluxos simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 5.2 Fluxos mais complexos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 5.2.1 Arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Lendo arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Escrevendo em arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.2.2 Fluxos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786 Exce¸˜es co 81 6.1 Begin . . . rescue . . . ensure . . . end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.2 Throw . . . catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847 M´dulos o 878 Threads 91 8.1 Timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 8.2 Criando usando Proc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 8.3 Sincroniza¸˜o . . . . ca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 8.4 Condition variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 969 Acessando banco de dados 99 9.1 Abrindo a conex˜o . . . . . . . . . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . 99 9.2 Executando queries que n˜o retornam resultado . . . a . . . . . . . . . . . . . . . . . . . . . 100 9.3 Recuperando dados do banco de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 9.4 Preparando comandos e usando parametros vari´veis a . . . . . . . . . . . . . . . . . . . . . 101 9.5 Metadados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 9.6 Trabalhando com blocos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 9.7 Output especializado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 9.7.1 Tabular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 9.7.2 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10610 XML 109 10.1 Lendo arquivos XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 10.2 Criando arquivos XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11011 YAML 113 11.1 Lendo arquivos YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 11.2 Gravando arquivos YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 4
  5. 5. 12 XSLT 11713 Usando Ruby na web 119 13.1 mod ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 13.1.1 Instalando o mod ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 13.1.2 Configurando o servidor Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 13.1.3 Testando o mod ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 13.2 eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.1 Instalando o eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.2 Configurando o servidor Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.3 Testando o eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.4 Sintaxe do eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 13.3 CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 13.3.1 Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 13.3.2 Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 13.3.3 Sess˜es . . . . . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12614 Interface Gr´fica a 131 14.1 Obtendo e compilando o m´dulo GTK2 o . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 14.2 Hello, GUI world! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 14.3 Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 14.4 Packing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 14.5 Posicionamento usando tabelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 14.6 Mais alguns componentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.6.1 CheckButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.6.2 ComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.6.3 Campos texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 14.6.4 Radio buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13815 Garbage collector 141 15.1 O algoritmo utilizado: mark-and-sweep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 15.2 Como funciona, na teoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 15.3 Como funciona, na pr´tica . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 15.4 Otimizando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14316 Unit Testing 147 16.1 A classe a ser testada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 16.2 Unidade de testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 16.3 Falhas nos testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 16.4 Novas funcionalidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15117 XML-RPC 155 17.1 Servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 17.2 Cliente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 17.3 Acessando de outras linguagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 5
  6. 6. 6
  7. 7. Um pouco de bate-papo . . .Eu comecei a fazer esse tutorial como sempre come¸o fazendo as minhas coisas: necessidade de me lem- cbrar depois.Como estou come¸ando a aprender a programar em Ruby agora (Nov/2004), quero fazer algumas canota¸˜es, me perdoem se em algum ponto eu fizer alguma bobagenzinha, mas depois de rirem disso me coenviem um email (eustaquiorangel@yahoo.com) para que eu possa corrigir o que estiver errado. :-)Tenho experiˆncia como programador j´ faz alguns bons anos, e j´ passei por v´rias linguagens, e no e a a adecorrer do manual vou citar algumas compara¸˜es entre o Ruby e Java —, Python, PHP, etc. Estou copresumindo que vocˆ tamb´m programe em alguma linguagem, sendo que esse n˜o ´ um tutorial para e e a eaprender a programar, e sim para aprender a programar em Ruby, com experiˆncia de programa¸˜o e caj´ adquirida em outras linguagens. aAo mesmo tempo, n˜o vou me ater muito em explicar as entranhas da linguagem aqui, apesar de mostrar aalgumas coisinhas. :-)Alguns c´digos tamb´m podem n˜o estar com sua otimiza¸˜o “no talo”, mas para efeito de tutorial, o e a ca´ melhor assim.eE sobre linguagens, deixe-me fazer um singelo protesto aqui. N˜o vou falar sobre qual ´ melhor ou a en˜o, por que discutir isso para mim ´ perda de tempo. a eN˜o por que eu saiba a resposta de qual ´, mas por que acho que s˜o todas linguagens boas e o que a e adifere nesse ponto s˜o como as pessoas as veˆm e as utilizam. Tenho v´rias cita¸˜es de outras linguagens a e a cono decorrer do texto, mas em car´ter puramente comparativo/informativo, e n˜o nos termos de “aquela a aporcaria de XYZ faz isso dessa maneira”. c a e e ˜Esse tipo de ca¸a `s bruxas ´ justamente o que vocˆ NAO vai encontrar aqui. J´ perdi muito tempo com aesse tipo de coisa, e espero que ao inv´s de vocˆ perder tamb´m sente e escreva c´digo na sua linguagem e e e opreferida do que ficar fazendo flamewars por a´ :-) ı.Ent˜o, vamos nessa. a Dedico esse trabalho ` minha filhinha Ana Isabella, que me ilumina todos os dias. a 7
  8. 8. 8
  9. 9. Cap´ ıtulo 1Introdu¸˜o ca1.1 O que ´ Ruby ePara explicar o que ´ Ruby, eu fa¸o uma tradu¸˜o livre do que Yukihiro “Matz” Matsumoto, seu criador, e c cadiz a respeito dela em http://www.ruby-lang.org/en/20020101.html:Ruby ´ uma linguagem de script interpretada para programa¸˜o orientada a objetos de um modo f´cil e e ca ar´pido. Ela tem v´rios recursos para processar arquivos de texto e para fazer tarefas de gerenciamento a ade sistema (assim como o Perl). Ela ´ simples, direto ao ponto, extens´ e port´vel. e ıvel aOh, preciso mencionar, ´ totalmente livre, o que significa n˜o s´ livre de precisar pagar para us´-la, e a o amas tamb´m a liberdade de usar, copiar, modificar e distribu´ e ı-la.Recursos do Ruby ˆ Ruby tem uma sintaxe simples, parcialmente inspirada por Eiffel e Ada. ˆ Ruby tem recursos de tratamento de exce¸˜es, assim como Java —e Python, para deixar mais f´cil co a o tratamento de erros. ˆ Os operadores do Ruby s˜o a¸ucar sint´tico para os m´todos. Vocˆ pode redefini-los facilmente. a c a e e ˆ Ruby ´ uma linguagem completa e pura orientada ` objetos. Isso significa que todo dado em Ruby e a ´ um objeto, n˜o do jeito de Python e Perl, mas mais do jeito do SmallTalk: sem exce¸˜es. Por e a co exemplo, em Ruby, o n´mero 1 ´ uma instˆncia da classe Fixnum. u e a ˆ A orienta¸˜o ` objetos do Ruby ´ desenhada cuidadosamente para ser completa e aberta ` me- ca a e a lhorias. Por exemplo, Ruby tem a habilidade de adicionar m´todos em uma classe, ou at´ mesmo e e em uma instˆncia durante o runtime! Ent˜o, se necess´rio, a instˆncia de uma classe *pode* se a a a a comportar diferente de outras instˆncias da mesma classe. a ˆ Ruby tem heran¸a unica, de prop´sito. Mas entende o conceito de m´dulos (chamados de Categories c ´ o o no Objective-C). M´dulos s˜o cole¸˜es de m´todos. Toda classe pode importar um m´dulo e pegar o a co e o seus m´todos. Alguns de n´s acham que isso ´ um jeito mais limpo do que heran¸a m´ltipla, que e o e c u ´ complexa e n˜o ´ usada tanto comparado com heran¸a unica (n˜o conte C++ aqui, pois l´ n˜o e a e c ´ a a a se tem muita escolha devido a checagem forte de tipo!). ˆ Ruby tem closures verdadeiras. N˜o apenas fun¸˜es sem nome, mas com bindings de v´riaveis a co a verdadeiras. ˆ Ruby tem blocos em sua sintaxe (c´digo delimitado por ’{’. . . ’}’ ou ’do’. . . ’end’). Esses blocos o podem ser passados para os m´todos, ou convertidos em closures. e ˆ Ruby tem um garbage collector que realmente ´ do tipo marca-e-limpa. Ele atua em todos os e objetos do Ruby. Vocˆ n˜o precisa se preocupar em manter contagem de referˆncias em libraries e a e ´ externas. E melhor para a sua sa´de. ;-) u 9
  10. 10. ˆ Escrever extens˜es em C para Ruby ´ mais f´cil que em Perl ou Python, em grande parte por o e a causa do garbage collector, e em parte pela boa API de extens˜es. A interface SWIG tamb´m est´ o e a dispon´ ıvel. ˆ Inteiros em Ruby podem (e devem) ser usados sem contar sua representa¸˜o interna. Existem ca inteiros pequenos (instˆncias da classe Fixnum) e grandes (Bignum), mas vocˆ n˜o precisa se a e a preocupar em qual est´ sendo utilizado atualmente. Se um valor ´ pequeno o bastante, um inteiro a e ´ um Fixnum, do contr´rio ´ um Bignum. A convers˜o ocorre automaticamente. e a e a ˆ Ruby n˜o precisa de declara¸˜o de vari´veis. Apenas usa a conven¸˜o de nomenclatura para a ca a ca delimitar o escopo das vari´veis. Por exemplo: ’var’ = vari´vel local, ’@var’ = vari´vel de instˆncia, a a a a ’$var’= vari´vel global. E n˜o precisa do uso cansativo do ’self’ em cada membro da instˆncia. a a a ˆ Ruby pode carregar bibliotecas de extens˜o dinamicamente, se o sistema operacional permitir. a ˆ Ruby tem um sistema de threading independente do sistema operacional. Ent˜o, para cada plata- a forma que vocˆ roda o Ruby, vocˆ tem multithreading de qualquer jeito, at´ no MS-DOS! ;-) e e e ˆ Ruby ´ altamente port´vel: ela ´ desenvolvida em sua maioria no Linux, mas funciona em muitos e a e tipos de UNIX, DOS, Windows 95/98/Me/NT/2000/XP, MacOS, BeOS, OS/2, etc.1.2 Onde encontro RubyVocˆ pode encontrar Ruby no seu site oficial na internet: ehttp://www.ruby-lang.orgL´ vocˆ encontra o c´digo-fonte e vers˜es para Windows —. Compilar o c´digo ´ r´pido e f´cil, no a e o o o e a avelho esquema tar xvzf ruby-$<versao>$.tgz ./configure make make installProcure na sua distribui¸˜o (se vocˆ usa GNU/Linux) algum pacote do Ruby. Se n˜o encontrar, compile- ca e ao e o disponibilize em algum lugar. Eu fiz um pacote para o Slackware, est´ dispon´ aqui: a ıvelhttp://beam.to/taq/downloads.phpSe vocˆ pegar o pacote, pegue tamb´m a assinatura PGP do arquivo, importe a minha chave p´blica e e u(784988BB) e fa¸a a conferˆncia. c e 10
  11. 11. Cap´ ıtulo 2Arrumando as coisas2.1 Preparando sua fonte de consultas´E sempre bom ter uma referˆncia das classes, m´dulos e m´todos dispon´ e o e ıveis em uma linguagem quandose est´ aprendendo. aRuby vem com um utilit´rio chamado ri que facilita a sua consulta ´ essa documenta¸˜o. Mas para ele a a capoder consultar alguma coisa, primeiro temos que gera-l´. aDepois de instalado o Ruby, v´ para o diret´rio onde vocˆ instalou os fontes e digite, por exemplo: a o e [taq@/usr/src/ruby-1.8.1]rdoc --ri *.c lib/*.rbIsso vai produzir a documenta¸˜o do core do Ruby, que vai ser armazenada no seu diret´rio /.rdoc. ca oAp´s isso podemos utilizar o ri dessa maneira, por exemplo: o [taq@ ]ri File ----------------------------------------------------------- Module: File A File is an abstraction of any file object accessible by the program and is closely associated with class IO File includes the methods of module FileTest as class methods, allowing you to write (for example) File.exist?("foo"). ...Se utilizarmos um console que tenha suporte a cores, podemos criar um alias: alias ri=ri -f ansi -TAssim o exemplo acima fica [taq@ ]ri File ----------------------------------------------------------- Module: File A File is an abstraction of any file object accessible by the program and is closely associated with class IO File includes the methods of module FileTest as class methods, allowing you to write (for example) File.exist?("foo"). ...2.2 Preparando o ambiente de trabalhoN˜o tem jeito melhor de aprender a programar em uma linguagem do que j´ ir colocando a m˜o na a a amassa. Ruby tem um programinha muito bom para ir testando o c´digo, o irb (interactive Ruby shell). oEstilo do Python, que podemos chamar e j´ ir digitando as coisas e vendo os resultados. aAntes de abrirmos o irb, vamos alterar o arquivo .irbrc, que fica no seu diret´rio home. o 11
  12. 12. ¸˜ ATENCAO Estou usando GNU/Linux durante todo esse tutorial, e presumo que voc^ est´ usando e a tamb´m. L´gico que voc^ pode rodar Ruby em qualquer dos sistemas operacionais e o e citados acima, mas eu realmente n~o tenho param^tros para lhe dizer como fazer a e as configura¸~es em outro sistema. coInsira require ’irb/completion’no arquivo.Ok, agora chame o irb simplesmente digitando irb no terminal: [taq@~]irb irb(main):001:0$>$Agora o irb j´ est´ pronto para ser usado. Vamos conhecer mais um pouco dele: a a irb(main):001:0> i = 10 => 10 irb(main):002:0> if i > 5 irb(main):003:1> puts "maior que 5" irb(main):004:1> else irb(main):005:1* puts "menor que 5" irb(main):006:1> end maior que 5 => nil irb(main):007:0>Separando o prompt pelos dois pontos (:), temos algumas se¸˜es: co ˆ O nome do programa que estamos rodando (main) ˆ O n´mero de linhas que digitamos (e estamos!) no irb u ˆ O n´ de profundidade que estamos ıvelO n´ de profundidade ´ incrementado sempre que abrimos uma express˜o que precisa de fechamento. ıvel e aSempre que o irb verificar que o c´digo precisa ser fechado, ele vai trocar o final do prompt por um oasterisco, ou aspas-duplas se n˜o fechamos uma String: a [taq@~]irb irb(main):001:0> s = "um teste irb(main):002:0" do irb" => "um teste ndo irb" irb(main):003:0>Olhem o n´ de profundidade alterado: ıvel [taq@~]irb irb(main):001:0> def teste(n) irb(main):002:1> if n > 10 irb(main):003:2> puts "teste" irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> 12
  13. 13. Cap´ ıtulo 3Conhecendo o b´sico da linguagem a3.1 Vari´veis aVamos destrinchar aqui alguns tipos b´sicos do Ruby, e como usar vari´veis com eles. a aApesar de ter sido dito que TUDO em Ruby ´ um objeto, vari´veis n˜o s˜o objetos, mas referˆncias para e a a a eesses.As vari´veis do Ruby s˜o muito simples de serem utilizadas pois utilizam a “duck typing”, como a a´ chamada carinhosamente a tipagem dinˆmica do Ruby. Para os que vieram do Java —, que tem umae atipagem est´tica, um bom exemplo seria a [taq@~]irb irb(main):001:0> v = "teste" => "teste" irb(main):002:0> v.class => String irb(main):003:0> v = 1 => 1 irb(main):004:0> v.class => Fixnum irb(main):005:0>Vale lembrar que Ruby tamb´m tem tipagem forte, isso ´, vamos receber um erro se tentarmos fazer e eisso: [taq@~]irb irb(main):001:0> i = 1 => 1 irb(main):002:0> s = "oi" => "oi" irb(main):003:0> x = i+s TypeError: String can’t be coerced into Fixnum from (irb):3:in ‘+’ from (irb):3 irb(main):004:0>Ent˜o, n˜o inventem de misturar uma coisa com a outra. :-) a aVamos dar uma olhadinha ali no output do irb. S´ para dar uma “coceirinha”, reparem que depois oque declarei a primeira vari´vel, pedi para ele verificar o valor do atributo class da vari´vel. Foi retor- a anado String, l´gico, pois a vari´vel v vale “teste” nesse caso. o aAgora olhem na segunda atribui¸˜o de valor. Indiquei que o valor de v ´ 1, e verificando o class foi ca e 13
  14. 14. retornado Fixnum, provando que o que o Matz disse na descri¸˜o do Ruby no come¸o desse tutorial ´ ca c everdade: TUDO ´ objeto em Ruby. eDuvidam? Olhem que legal: [taq@~]irb irb(main):001:0> i = 1 => 1 irb(main):002:0> i.methods => ["%", "between?", "send", "<<", "prec", "&", "object_id", ">>", "size", "singleton_methods", "__send__", "round", "equal?", "taint", "method", "id2name", "*", "next", "frozen?", "instance_variable_get", "divmod", "+", "kind_of?", "integer?", "chr", "to_a", "instance_eval", "-", "prec_i", "/", "type", "protected_methods", "extend", "truncate", "to_sym", "|", "eql?", "modulo", "instance_variable_set", "~", "hash", "zero?", "is_a?", "to_s", "prec_f", "singleton_method_added", "class", "tainted?", "private_methods", "^", "step", "untaint", "+@", "upto", "-@", "remainder", "id", "**", "nonzero?", "to_i","<", "inspect", "<=>", "==", "floor", ">", "===", "succ", "clone", "public_methods", "quo", "display", "downto", ">=", "respond_to?", "<=", "freeze", "abs", "to_f", "__id__", "coerce", "=~", "methods", "ceil","nil?", "dup", "to_int", "div", "instance_variables", "[]", "instance_of?", "times"]Esses s˜o os m´todos p´ blicos da instˆncia da classe (seria equivalente ` uma chamada i.public methods). a e u a aPara vermos os m´todos privados da instˆncia da classe, podemos usar i.private methods. e aLembrem-se que estamos falando de m´todos da instˆncia da classe, mais tarde vamos falar dos e am´todos da classe, sendo eles p´blicos, privados e protegidos. Mas isso mais tarde. e uAgora vamos continuar a falar de vari´veis. a3.1.1 Escopo das vari´veis aPara declarar uma vari´vel no escopo privado, ´ s´ fazer isso: a e o [taq@~]irb irb(main):001:0> i = 1 => 1 irb(main):002:0> puts i 1 => nil irb(main):003:0>Aqui tem um m´todo novo, o puts, que ´ um m´todo de kernel do Ruby. Isso implica que pode- e e emos o utilizar sem precisar especificar o objeto ` que ele faz parte (Kernel). A declara¸˜o completa ´ a ca eKernel.puts. O puts nada mais faz que imprimir o resultado da express˜o que vocˆ passou para ele, a equebrando a linha no final.Para declarar uma v´riavel p´ blica, utilizamos a u [taq@~]irb irb(main):001:0> $i = 1 => 1 irb(main):002:0>e pronto. Declarando a vari´vel com um caracter $ na frente do nome j´ a torna p´blica. a a uTem mais um tipo de vari´vel, que ´ a de instˆncia de classe, mas s´ vamos falar nela quando che- a e a ogarmos no assunto de classes. :-) 14
  15. 15. 3.2 Tipos b´sicos a3.2.1 Blocos de c´digo oAntes de apresentar qualquer um dos tipos, quero mostrar uma coisa essencial em Ruby, que s˜o os ablocos de c´digo. oBlocos de c´digo s˜o umas das boas sacadas de Ruby, e podem ser peda¸os de c´digo delimitados por { o a c oe }: {puts ’Oi mundo!’}ou, para blocos maiores, delimitados por do e end: do puts ’Oi mundo!’ puts ’Aqui tem mais espa¸o’ c endA conven¸˜o ´ usar as chaves para blocos de uma linha e do . . . end para blocos maiores. ca eVamos ver muita coisa sobre blocos de c´digo mais adiante. Blocos de c´digo, juntamente com ite- o orators, s˜o muito utilizados em Ruby, s˜o uma das pe¸as-chaves da linguagem e v˜o aparecer em muitos a a c aexemplos dos tipos b´sicos abaixo. Se vocˆ n˜o entendeu muita coisa, n˜o tem problema, vamos ter uma a e a aexplica¸˜o mas extensa sobre isso logo. ca3.2.2 N´ meros uPodemos ter vari´veis dos tipos inteiro ou ponto flutuante. aExemplos de inteiros: [taq@~]irb irb(main):001:0> i1 = 1 => 1 irb(main):002:0> i2 = 123 => 123 irb(main):003:0> i3 = -1000 => -1000 irb(main):004:0> i4 = 3_000_000_000 => 3000000000 irb(main):005:0> puts i1.class Fixnum => nil irb(main):006:0> puts i2.class Fixnum => nil irb(main):007:0> puts i3.class Fixnum => nil irb(main):008:0> puts i4.class Bignum => nil irb(main):009:0>N˜o podemos usar v´ a ırgulas em vari´veis, mas se acharmos que fica mais leg´ a ıvel, podemos usar subli-nhado para separar os milhares, como no exemplo dos 3 bilh˜es acima (algu´m tem isso na conta? :-). o eOutra coisa que eu fiz ali foi mostrar o tipo de cada vari´vel. Como o Matz disse tamb´m na des- a ecri¸˜o inicial, dependendo do n´mero que vocˆ utiliza, o Ruby j´ troca automaticamente o tipo. As trˆs ca u e a eprimeiras vari´veis s˜o do tipo Fixnum, enquanto a ultima n˜o coube no Fixnum e foi automaticamente a a ´ a 15
  16. 16. usado o Bignum.Exemplos de ponto flutuante: [taq@~]irb irb(main):001:0> f1 = 1.23 => 1.23 irb(main):002:0> f2 = -57.08 => -57.08 irb(main):003:0> f3 = 15.058e-4 => 0.0015058 irb(main):004:0> f1.class => Float irb(main):005:0> f2.class => Float irb(main):006:0> f3.class => Float irb(main):007:0>Tamb´m podemos criar n´meros usando as formas hexadecimal, octal e bin´ria: e u a [taq@~]irb irb(main):001:0> hex = 0xFF => 255 irb(main):002:0> oct = 0377 => 255 irb(main):003:0> bin = 0b11111111 => 255 irb(main):004:0>3.2.3 BooleanosS˜o os valores true e false. Reparem que est˜o em min´ sculas. a a uAproveitando o gancho dos booleanos, o valor nulo em Ruby ´ definido como nil, sendo que false e nil s˜o e aos unicos valores que s˜o reconhecidos como valores indicando falso, mas s˜o de classes e comportamentos ´ a adiferentes: [taq@~]irb irb(main):001:0> t = true => true irb(main):002:0> f = false => false irb(main):003:0> n = nil => nil irb(main):004:0> t.class => TrueClass irb(main):005:0> f.class => FalseClass irb(main):006:0> n.class => NilClass irb(main):007:0>A recomenda¸˜o ´ que m´todos predicados (que terminam com ? no final, mais sobre isso depois) retornem ca e etrue ou false, enquanto outros m´todos que precisam indicar falha retornem nil. e3.2.4 StringsQualquer “palavra” ou conjunto de palavras podem ser armazenados como uma String: 16
  17. 17. [taq@~]irb irb(main):001:0> s1 = "oi" => "oi" irb(main):002:0> s2 = "oi, amigo!" => "oi, amigo!" irb(main):003:0> s3 = "oi, ’mano’!" => "oi, ’mano’!" irb(main):004:0> s1.class => String irb(main):005:0>Vamos aproveitar que estamos falando de Strings e lembrar que, como foi dito acima, vari´veis s˜o a areferˆncias para objetos. Para ter uma prova disso, vamos ver um exemplo: e [taq@~]irb irb(main):001:0> my_nick = "TaQ" => "TaQ" irb(main):002:0> my_nick_copy = my_nick => "TaQ" irb(main):003:0> my_nick[0] = ’S’ => "S" irb(main):004:0> puts my_nick SaQ => nil irb(main):005:0> puts my_nick_copy SaQ => nil irb(main):006:0>O que aconteceu aqui? Eu s´ troquei o primeiro caracter da vari´vel my nick, n˜o da my nick copy o a a(falando nisso, vocˆ pode manipular Strings usando [] da mesma maneira que em outras linguagens)! eBom, nesse caso, my nick copy aponta para o mesmo lugar onde se encontra o valor de my nick, por issoque quando vocˆ alterou uma, alterou a outra junto. eSe n˜o quisermos que um objeto seja alterado, podemos usar o m´todo freeze nele: a e [taq@~]irb irb(main):001:0> my_nick = "TaQ" => "TaQ" irb(main):002:0> my_nick_copy = my_nick => "TaQ" irb(main):003:0> my_nick.freeze => "TaQ" irb(main):004:0> my_nick[0] = ’S’ TypeError: can’t modify frozen string from (irb):4:in ‘[]=’ from (irb):4 irb(main):005:0> my_nick_copy[0] = ’S’ TypeError: can’t modify frozen string from (irb):5:in ‘[]=’ from (irb):5 irb(main):006:0> my_nick => "TaQ" irb(main):007:0> my_nick_copy => "TaQ" irb(main):008:0>Para ter resultados distintos entre as vari´veis, baseando o valor de uma na outra, ter´ a ıamos que fazer: 17
  18. 18. [taq@~]irb irb(main):001:0> my_nick = "TaQ" => "TaQ" irb(main):002:0> my_nick_copy = my_nick.dup => "TaQ" irb(main):003:0> my_nick[0] = ’S’ => "S" irb(main):004:0> puts my_nick SaQ => nil irb(main):005:0> puts my_nick_copy TaQ => nil irb(main):006:0>O m´todo dup duplica o objeto, criando uma nova c´pia, que foi atribu´ ` vari´vel my nick copy. e o ıda a aEnt˜o, quando trocamos o primeiro caracter de my nick, estamos alterando somente ela e n˜o mais a amy nick copy junto.Podemos usar uma feature chamada de heredoc para criar “stringonas”: [taq@~]irb irb(main):001:0> s = <<FIM irb(main):002:0" Uma String realmente irb(main):003:0" grande com alguns irb(main):004:0" saltos de linhas, para irb(main):005:0" demonstrar o heredoc! irb(main):006:0" FIM => "Uma String realmentengrande com algunsnsaltos de linhas, parandemonstrar o heredoc!n" irb(main):007:0> puts s Uma String realmente grande com alguns saltos de linhas, para demonstrar o heredoc! => nil irb(main):008:0>Definimos uma vari´vel, que tem seu valor atribu´ logo ap´s encontrarmos uma string semelhante ` a ıdo o aque vem depois de <<. No caso usei FIM, mas fica a seu crit´rio qual string usar de terminador. Se equiser escrever PINDAMONHANGABA, pode. :-)Para concatenar Strings, podemos usar + ou << (lembraram de C++?): [taq@~/trash]irb irb(main):001:0> s = "Oi, " => "Oi, " irb(main):002:0> s + "mundo!" => "Oi, mundo!" irb(main):003:0> s << "mundo!" => "Oi, mundo!" irb(main):004:0>Fica a dica que << ´ mais r´pido, pois n˜o gera um novo objeto como +: e a a [taq@~]irb irb(main):001:0> s = "teste" => "teste" irb(main):002:0> s.object_id => -605086198 18
  19. 19. irb(main):003:0> s += " concatenado" => "teste concatenado" irb(main):004:0> s => "teste concatenado" irb(main):005:0> s.object_id => -605094768 irb(main):006:0> s2 = "teste" => "teste" irb(main):007:0> s2.object_id => -605105148 irb(main):008:0> s2 << " concatenado" => "teste concatenado" irb(main):009:0> s2 => "teste concatenado" irb(main):010:0> s2.object_id => -605105148 irb(main):011:0>No caso de s += “concatenado”, ´ interpretado como s = s + “concatenado”, por isso que gera eum novo objeto.3.2.5 ConstantesConstantes s˜o vari´veis que tem seu nome come¸ado com uma letra mai´ scula. a a c u“O que? S´ isso?” vocˆ poderia me perguntar. S´. o e o“Mas n˜o fica meio confuso com nomes de classes que come¸am em mai´sculas?” uhnnn at´ fica, mas a c u e´ pr´tico.e a“Ent˜o, por exemplo, ao inv´s de eu ter em Java —: public static final double Pi = 3.1415926; eu a e o ´s´ teria que escrever Pi?”. E isso a´ ı.“Tem certeza que isso ´ uma constante?”. Ok, vamos ver: e [taq@~]irb irb(main):001:0> Pi = 3.1415926 => 3.1415926 irb(main):002:0> Pi = 10 (irb):2: warning: already initialized constant Pi => 10 irb(main):003:0>Viu? Declarei a vari´vel, e quando fui alterar seu conte´do, fui informado que n˜o deveria, pois ´ uma a u a econstante.Fica um fato curioso que Ruby, diferente de outras linguagens, permite que vocˆ altere a constante, e(“mas n˜o era uma constante?”) mas gera um warning alertando sobre isso. a3.2.6 RangesIntervalos. Podemos declarar de duas maneiras: incluindo ou n˜o o ultimo valor a que nos referimos em a ´sua declara¸ao. Por exemplo: c˜ [taq@~/code/java]irb irb(main):001:0> r = 0..10 => 0..10 irb(main):002:0> r2 = 0...10 => 0...10 irb(main):003:0>No primeiro caso, a range vai conter n´meros de 0 at´ 10, incluindo o 10. No segundo caso, vai de 0 at´ u e e9.Como regrinha dos pontinhos, menos ´ mais, quando se tem menos pontos, se tem mais valores na range. e 19
  20. 20. 3.2.7 ArraysArrays podem conter v´rios tipos de objetos (ou n˜o): a a [taq@~]irb irb(main):001:0> a = [’apenas’,1,’teste’] => ["apenas", 1, "teste"] irb(main):002:0>Para Arrays com somente Strings, podemos usar o atalho %w, ficaria assim: [taq@~]irb irb(main):001:0> a = %w(homer marge bart lisa maggie o bebezinho) => ["homer", "marge", "bart", "lisa", "maggie o bebezinho"] irb(main):002:0>Se precisarmos de uma String com mais de uma palavra, usamos o caracter como mostrado acima.Inserir elementos no Array ´ facil, usando push: e [taq@~]irb irb(main):001:0> a = [] => [] irb(main):002:0> a.push "um" => ["um"] irb(main):003:0> a.push "dois" => ["um", "dois"] irb(main):004:0> a.push "tres" => ["um", "dois", "tres"] irb(main):005:0> a.push "quatro" => ["um", "dois", "tres", "quatro"] irb(main):006:0>ou usando o operador <<: [taq@~]irb irb(main):001:0> a = [] => [] irb(main):002:0> a << "um" => ["um"] irb(main):003:0> a << "dois" => ["um", "dois"] irb(main):004:0> a << "tres" => ["um", "dois", "tres"] irb(main):005:0>Podemos fazer com um Array algo semelhante `s list comprehensions do Python, que ´ processar a eos elementos do Array e criar um novo, baseado em uma condi¸˜o. Por exemplo, quero processar os caelementos pares de um Array e criar um novo com o dobro dos valores pares: [taq@~]irb irb(main):001:0> a = [1,2,3,4,5] => [1, 2, 3, 4, 5] irb(main):002:0> a2 = a.find_all {|v| v%2==0}.map{|v| v*2} => [4, 8] irb(main):003:0>Podemos usar collect tamb´m no lugar de map, ´ uma quest˜o de gosto ali. :-) e e aOrdenando um array: 20
  21. 21. [taq@~]irb irb(main):001:0> a = ["um","dois","tres"] => ["um", "dois", "tres"] irb(main):002:0> a.sort => ["dois", "tres", "um"] irb(main):003:0>Podemos usar o m´todo sort assim tamb´m: e e [taq@~]irb irb(main):001:0> a = ["um","dois","tres"] => ["um", "dois", "tres"] irb(main):002:0> a.sort {|e1,e2| e1[0]<=>e2[0]} => ["dois", "tres", "um"] irb(main):003:0>Usando o m´todo sort com um bloco, s˜o enviados dois parˆmetros para o bloco, que os compara usando e a ao operador <=>. Podemos tamb´m utilizar o m´todo sort by, que ´ mais r´pido e eficiente quando e e e aprecisamos ordenar por alguma propriedade ou express˜o do valor sendo avaliado: a [taq@~]irb irb(main):001:0> a = ["um","dois","tres"] => ["um", "dois", "tres"] irb(main):002:0> a.sort_by {|e| e[0]} => ["dois", "tres", "um"] irb(main):003:0>Nesse caso, foi avaliado a ordem alfab´tica das palavras. Se eu quisesse ordenar o Array pelo tamanho edas palavras, poderia usar: [taq@~]irb irb(main):001:0> a = ["tres","dois","um"] => ["tres", "dois", "um"] irb(main):002:0> a.sort_by {|e| e.length} => ["um", "dois", "tres"] irb(main):003:0>Podemos usar o m´todo any? para verificar se tem algum elemento de um Array que se encaixe em uma econdi¸˜o determinada por um bloco: ca [taq@~]irb irb(main):001:0> a = [1,2,50,3] => [1, 2, 50, 3] irb(main):002:0> a.any? {|v| v>10} => true irb(main):003:0> a.any? {|v| v>100} => false irb(main):004:0>Se quisermos testar se todos os elementos do Array satisfazem uma condi¸˜o, podemos utilizar o m´todo ca eall?: [taq@~]irb irb(main):001:0> a = [1,2,3,4,5] => [1, 2, 3, 4, 5] irb(main):002:0> a.all? {|v| v>0} => true irb(main):003:0> a.all? {|v| v>10} => false irb(main):004:0> 21
  22. 22. Tamb´m podemos particionar um Array, usando o m´todo partition: e e [taq@~]irb irb(main):001:0> a = [1,2,3,4,5,6,7,8,9,10] => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] irb(main):002:0> par,impar = a.partition {|e| e%2==0} => [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]] irb(main):003:0> par => [2, 4, 6, 8, 10] irb(main):004:0> impar => [1, 3, 5, 7, 9] irb(main):005:0>O que aconteceu ´ que foram retornados dois novos Arrays, o primeiro com elementos que atendiam a econdi¸˜o especificada no bloco, e o segundo com os elementos que n˜o atendiam a condi¸˜o. ca a ca3.2.8 HashesUm Hash ´ basicamente um Array com ´ e ındices para seus elementos (uma analogia com Java —seriam osobjetos HashMap e Hashtable). Vejamos um exemplo: [taq@~/code/ruby]irb irb(main):001:0> h = {1=>"elemento 1","um"=>"elemento um"} => {"um"=>"elemento um", 1=>"elemento 1"} irb(main):002:0> h[1] => "elemento 1" irb(main):003:0> h["um"] => "elemento um" irb(main):004:0>Podemos utilizar tamb´m s´ e ımbolos para a chave do Hash: [taq@~/code/ruby]irb irb(main):001:0> h = {:um=>"elemento 1",:dois=>"elemento 2"} => {:um=>"elemento 1", :dois=>"elemento 2"} irb(main):002:0> h[:um] => "elemento 1" irb(main):003:0> h[:dois] => "elemento 2" irb(main):004:0> Uma pequena compara¸˜o ca Primeiro, xˆ, flamewar. Vou fazer uma compara¸˜o com Arrays e Hashes aqui de uma o ca maneira saud´vel. a Eu tive que fazer um pequeno teste com alguns Arrays em PHP, para um programa que fiz aqui, onde eu copiava o primeiro Array para mais dois, removia os elementos do primeiro usando pop, depois invertia e usava pop no segundo, e finalmente removia os elementos do terceiro usando shift. No meu teste, Arrays de 15000 elementos foram preenchidos e tiveram seus elementos remo- vidos com pop praticamente instantˆneamente, invertendo e removendo idem, mas usando a reverse/shift foram 31 segundos. Fiz o mesmo teste com Ruby. Foi instantˆneo! Resolvi aumentar o tamanho dos Array a para 10 vezes mais, 150000 elementos. Levou 4 segundos! 22
  23. 23. Curioso com o teste, fui verificar a causa disso e descobri: ao contr´rio de Ruby (e ou- a tras linguagens tamb´m) todos os Arrays em PHP s˜o na verdade, Hashes!. Isso d´ e a a praticidade, mas d´ para ver o pre¸o que se paga e o que se ganha usando uma linguagem a c com distin¸˜o entre os dois. ca3.2.9 S´ ımbolosPense em s´ ımbolos como “String levinhas”. Eles representam nomes e algumas Strings dentro do inter-pretador do Ruby, e s˜o sempre o mesmo objeto durante a execu¸˜o de um programa. a caS´ ımbolos s˜o criados usando : na frente do seu nome, como em: a :um :doisComo demonstrado acima.Vamos dar uma olhada no fato de serem sempre o mesmo objeto, pegando o exemplo da documenta¸˜o cado Ruby: module One class Fred end $f1 = :Fred end module Two Fred = 1 $f2 = :Fred end def Fred() end $f3 = :Fred $f1.id #=> 2514190 $f2.id #=> 2514190 $f3.id #=> 2514190Mesmo id! :-)3.2.10 Express˜es regulares oExpress˜es regulares s˜o facilmente criadas, delimitando-as com /: o a [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0>E facilmente testadas, usando o operador de correspondˆncia =˜ ou de n˜o-correspondˆncia !˜: e a e [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0> "123" =~ er => 0 irb(main):003:0> "123" !~ er => false irb(main):004:0> "abc" =~ er => nil irb(main):005:0> "abc" !~ er => true irb(main):006:0> 23
  24. 24. Express˜es regulares tamb´m podem ser criadas usando o construtor da classe ou %r: o e [taq@~]irb irb(main):001:0> er = Regexp.new("^[0-9]") => /^[0-9]/ irb(main):002:0> er2 = %r{^[0-9]} => /^[0-9]/ irb(main):003:0>Vamos fazer um teste mais pr´tico, usando a express˜o regular acima, “se a linha come¸ar com um a a cn´mero”, usando um if para deixar mais claro (mas tem jeitos de fazer isso mais eficientemente): u [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0> if "123" =~ er irb(main):003:1> puts "casou!" irb(main):004:1> else irb(main):005:1* puts "N~O casou!" A irb(main):006:1> end casou! => nil irb(main):007:0> if "abc" =~ er irb(main):008:1> puts "casou!" irb(main):009:1> else irb(main):010:1* puts "N~O casou!" A irb(main):011:1> end N~O casou! A => nilIsso poderia ser escrito como: [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0> puts ("123" =~ er ? "":"n~o ")+"casou" a casou => nil irb(main):003:0> puts ("abc" =~ er ? "":"n~o ")+"casou" a n~o casou aMas se vocˆ n˜o sabe o que ´ aquela constru¸˜o (condi¸˜o?verdadeiro:falso) talvez se eu mostrasse assim e a e ca cade primeira pudesse confundir um pouco a coisa aqui.Podemos utilizar o m´todo match para pegarmos os tokens de uma string que “casa” com nossa ex- epress˜o regular: a [taq@~]irb irb(main):001:0> er = /(..)/(..)/(....)/ => /(..)/(..)/(....)/ irb(main):002:0> mt = er.match("20/06/2005") => #<MatchData:0xb7dd5dd0> irb(main):003:0> mt.length => 4 irb(main):004:0> mt[0] => "20/06/2005" irb(main):005:0> mt[1] => "20" irb(main):006:0> mt[2] 24
  25. 25. => "06" irb(main):007:0> mt[3] => "2005" irb(main):008:0> mt = er.match("20062005") => nil irb(main):009:0>No exemplo, se a string “casar” com a express˜o, vai ser retornado um objeto do tipo MatchData , aou nil se n˜o “casar”. No objeto retornado podemos verificar o seu tamanho, que inclui a string que apesquisamos, seguida por seus tokens (iniciando em 1).Podemos procurar em uma String onde uma express˜o regular “casa” usando index : a [taq@~]irb irb(main):001:0> "eustaquio".index(/taq/) => 3 irb(main):002:0>Tamb´m podemos usar o m´todo gsub da String para trocar seu conte´do utilizando uma express˜o e e u aregular: [taq@~]irb irb(main):001:0> "eustaquio".gsub(/qu/,’c’) => "eustacio" irb(main):002:0>Troquei meu nome ali por “Eust´cio” (que ´ o nome de um tiozinho ranzinza que vive assustando um a epobre cachorrinho em um desenho animado que tem por a´ :-) ı).Express˜es regulares tamb´m s˜o uma m˜o-na-roda quando usadas com iterators, como por exemplo: o e a a [taq@~]irb irb(main):001:0> a = %w(um dois tres quatro cinco seis sete oito nove dez) => ["um", "dois", "tres", "quatro", "cinco", "seis", "sete", "oito", "nove", "dez"] irb(main):002:0> a.grep(/s$/) => ["dois", "tres", "seis"]Nesse caso usei o m´todo grep no array, que por ter um m´todo each, torna dispon´ e e ıvel os m´todos eadicionais do m´dulo Enumerable, entre eles, grep. No exemplo eu pedi para filtrar os elementos que oeram terminados com “s”.Outro exemplo seria se tivermos um arquivo com os dados: [taq@~]cat teste.txt um dois tres quatro cinco seis sete oito nove dez [taq@~]irb irb(main):001:0> File.open("teste.txt").grep(/s$/) do |r| irb(main):002:1* puts r irb(main):003:1> end dois tres seis 25
  26. 26. 3.2.11 ProcsProcs s˜o blocos de c´digo associados ` uma vari´vel: a o a a [taq@~]irb irb(main):001:0> vezes3 = Proc.new {|n| n*3} => #<Proc:0xb7de21fc@(irb):1> irb(main):002:0> vezes3.call(1) => 3 irb(main):003:0> vezes3.call(2) => 6 irb(main):004:0> vezes3.call(3) => 9 irb(main):005:0>Podemos transformar um bloco de c´digo em uma Proc usando lambda: o [taq@~]irb irb(main):001:0> vezes3 = lambda {|n| n*3} => #<Proc:0xb7dd96c0@(irb):1> irb(main):002:0> vezes3.call(1) => 3 irb(main):003:0> vezes3.call(2) => 6 irb(main):004:0> vezes3.call(3) => 9 irb(main):005:0>3.2.12 M´todos eM´todos tamb´m s˜o muito f´ceis de serem declarados. S˜o definidos usando def, terminando com end e e a a a(mais sobre isso na pr´xima se¸˜o): o ca [taq@~]irb irb(main):001:0> def diga_oi irb(main):002:1> puts "oi!" irb(main):003:1> end => nil irb(main):004:0> diga_oi oi! => nil irb(main):005:0>Retornando valoresOlhem que legal: [taq@~]irb irb(main):001:0> def vezes(n1,n2) irb(main):002:1> n1*n2 irb(main):003:1> end => nil irb(main):004:0> vezes(3,4) => 12 irb(main):005:0>U´! Cadˆ o return ali? N˜o precisa. O valor do retorno do m´todo nesse caso ´ a ultima express˜o e e a e e ´ aavaliada, no caso, 3 vezes 4.Tamb´m podemos retornar mais de um resultado (na verdade, apenas um objeto, complexo ou n˜o, e a´ retornado, mas d´-se a impress˜o que s˜o v´rios):e a a a a 26
  27. 27. [taq@~]irb irb(main):001:0> def cinco_multiplos(n) irb(main):002:1> (1..5).map {|v| n*v} irb(main):003:1> end => nil irb(main):004:0> n1, n2, n3, n4, n5 = cinco_multiplos(5) => [5, 10, 15, 20, 25] irb(main):005:0> puts "m´ltiplos de 5: #{n1},#{n2},#{n3},#{n4},#{n5}" u m´ltiplos de 5: 5,10,15,20,25 u => nil irb(main):006:0>Recebendo parˆmetros aM´todos tamb´m recebem parˆmetros (que novidade ehehe) e retornam valores: e e a [taq@~]irb irb(main):001:0> def vezes(n1,n2) irb(main):002:1> return n1*n2 irb(main):003:1> end => nil irb(main):004:0> vezes(3,4) => 12 irb(main):005:0>M´todos tamb´m podem receber, como no PHP, argumentos com valores default, por exemplo: e e [taq@~]irb irb(main):001:0> def hello(s="Desconhecido") irb(main):002:1> puts "Oi, #{s}!" irb(main):003:1> end => nil irb(main):004:0> hello("TaQ") Oi, TaQ! => nil irb(main):005:0> hello Oi, Desconhecido! => nil irb(main):006:0>Ent˜o, se n˜o passarmos um argumento, ele assume o que foi especificado como default. a aTamb´m podemos ter parˆmetros vari´veis, por exemplo: e a a [taq@~]irb irb(main):001:0> def vargars(*args) irb(main):002:1> args.each {|v| puts "parametro recebido:#{v}"} irb(main):003:1> end => nil irb(main):004:0> vargars(1,2) parametro recebido:1 parametro recebido:2 => [1, 2] irb(main):005:0> vargars(1,2,3,4,5) parametro recebido:1 parametro recebido:2 parametro recebido:3 parametro recebido:4 27
  28. 28. parametro recebido:5 => [1, 2, 3, 4, 5] irb(main):006:0>Os parˆmetros vari´veis vem na forma de um Array, e para indicar no m´todo esse tipo de parˆmetro, a a e a´ s´ colocar um asterisco (*) na frente do nome do parˆmetro.e o aPodemos passar um bloco para o m´todo, executando-o com yield: e [taq@~]irb irb(main):001:0> def teste(n) irb(main):002:1> yield(n) irb(main):003:1> end => nil irb(main):004:0> teste(2) {|i| i*i} => 4 irb(main):005:0> teste(3) {|i| i*i} => 9 irb(main):006:0> teste(4) {|i| i*i} => 16 irb(main):007:0>Para testar se o m´todo recebeu um bloco, podemos usar block given?: e [taq@~]irb dirb(main):001:0> def teste(n) irb(main):002:1> if block_given? irb(main):003:2> yield(n) irb(main):004:2> else irb(main):005:2* puts "n~o foi passado um bloco!" a irb(main):006:2> end irb(main):007:1> end => nil irb(main):008:0> teste(2) {|i| i*i} => 4 irb(main):009:0> teste(3) {|i| i*i} => 9 irb(main):010:0> teste(4) {|i| i*i} => 16 irb(main):011:0> teste(5) n~o foi passado um bloco! a => nil irb(main):012:0>E se passarmos o ultimo argumento de um m´todo com um & na frente, um bloco passado como parˆmetro ´ e aser´ convertido em uma Proc e associado ao parˆmetro: a a [taq@~]irb irb(main):001:0> def teste(n,&b) irb(main):002:1> puts b.call(n) irb(main):003:1> end => nil irb(main):004:0> teste(2) {|i| i*i} 4 => nil irb(main):005:0> teste(3) {|i| i*i} 9 => nil irb(main):006:0> teste(4) {|i| i*i} 28
  29. 29. 16 => nil irb(main):007:0>Para converter uma Proc em um bloco de c´digo em um parˆmetro do m´todo, vocˆ pode usar o caracter o a e e& antes do nome da Proc: [taq@~]irb irb(main):001:0> quadrado = Proc.new {|i| i*i} => #<Proc:0xb7de2080@(irb):1> irb(main):002:0> def teste(n) irb(main):003:1> puts yield(n) irb(main):004:1> end => nil irb(main):005:0> teste(3,&quadrado) 9 => nil irb(main):006:0>Como os parˆmetros s˜o enviados a aOs parˆmetros s˜o passados por c´pia da referˆncia do objeto, ent˜o, se alterarmos um objeto que a a o e afoi passado como parˆmetro, dentro de um m´todo, e ele puder ser mut´vel, ele refletir´ fora do a e a am´todo. Por exemplo: e [taq@~]irb irb(main):001:0> s = "Oi, mundo!" => "Oi, mundo!" irb(main):002:0> s.object_id => -605086718 irb(main):003:0> def maiusculas(s) irb(main):004:1> s.upcase! irb(main):005:1> end => nil irb(main):006:0> maiusculas(s) => "OI, MUNDO!" irb(main):007:0> s => "OI, MUNDO!" irb(main):008:0> s.object_id => -605086718 irb(main):009:0>Foi criada uma String (s), e logo depois verifiquei seu id. Dentro do m´todo alterei o parˆmetro usando o e am´todo upcase! verifiquei seu valor (que foi alterado para maiusc´las) e seu id, que continua o mesmo, e uent˜o, o objeto foi alterado dentro do m´todo, usando como referˆncia o objeto que ele apontava, que a e epode ser mut´vel. a ATENCAO!¸˜ M´todos que alteram o valor e estado de um objeto geralmente tem um outro m´todo de e e mesmo nome, por´m com um ! no final. Esses s˜o os chamados m´todos destrutivos. A e a e vers˜o sem ! pega uma c´pia da referˆncia, faz a mudan¸a, e retorna um novo objeto. Os a o e c m´todos destrutivos alteram o pr´prio objeto. e oSe n˜o us´ssemos o !, somente retornando o valor convertido, ter´ a a ıamos retornado outro objeto, criadodentro do m´todo, no seu retorno (pelo fato de s.upcase ser a ultima express˜o avaliada no m´todo). Se e ´ a eus´ssemos o !, o objeto retornado seria o mesmo que foi alterado. aNo exemplo abaixo, o parˆmetro n˜o foi alterado, mas foi retornado um novo objeto na chamada do a am´todo, atribu´ ` referˆncia anterior, s. Isso pode ser comprovado verificando seu id: e ıdo a e 29
  30. 30. [taq@~]irb irb(main):001:0> s = "Oi, mundo!" => "Oi, mundo!" irb(main):002:0> s.object_id => -605086718 irb(main):003:0> def maiusculas(s) irb(main):004:1> s.upcase irb(main):005:1> end => nil irb(main):006:0> maiusculas(s) => "OI, MUNDO!" irb(main):007:0> s => "Oi, mundo!" irb(main):008:0> s.object_id => -605086718 irb(main):009:0> s = maiusculas(s) => "OI, MUNDO!" irb(main):010:0> s => "OI, MUNDO!" irb(main):011:0> s.object_id => -605122958 irb(main):012:0>Para alterar o valor de vari´veis do tipo Fixnum (Fixnum’s s˜o imut´veis), precisar´ a a a ıamos fazer do se-gundo modo, retornando um novo objeto para a sua vari´vel apontando para o seu Fixnum, pois eles an˜o podem ser alterados. aDeixa eu tentar deixar mais vis´ aqui: ıvel def teste1(s) print "Rodando TESTE1n" print "valor #{s}, id #{s.object_id}n" # Aqui ele cria um novo objeto com o valor da referencia em maiusculas # e aponta a referencia de s (ATENC~O! ele troca a refer^ncia de s, ¸A e # definida localmente aqui, para a localiza¸~o do novo objeto, e n~o ca a # interfere com a vari´vel externa do m´todo que gerou s como a e # par^metro! a s = s.upcase print "valor #{s}, id #{s.object_id} (aqui tem que ter um id diferente)nn" # Aqui ele retorna s, com sua nova refer^ncia, apontando para o novo objeto e s end def teste2(s) print "Rodando TESTE2n" print "valor #{s}, id #{s.object_id}n" # M´todo destrutivo ` frente! Vai agir direto no objeto e a # que se encontra na refer^ncia apontada por s e s.upcase! print "valor #{s}, id #{s.object_id}nn" s end s1 = "teste" # s1 aponta para um objeto do tipo String, com conte´do "teste" u s2 = s1 # s2 aponta para s1 sd = s1.dup # duplica para outro 30
  31. 31. print "Vamos verificar os objetos:n" print "s1 id:#{s1.object_id}, vale #{s1}n" print "s2 id:#{s2.object_id}, vale #{s2}n" print "sd id:#{sd.object_id}, vale #{sd} (objeto duplicado, id diferente!)nn" s3 = teste1(s1) print "Vamos verificar os objetos:n" print "s1 id:#{s1.object_id}, vale #{s1}n" print "s2 id:#{s2.object_id}, vale #{s2}n" print "s3 id:#{s3.object_id}, vale #{s3} (aqui tem que ter um id diferente)n" print "sd id:#{sd.object_id}, vale #{sd} (objeto duplicado, id diferente!)nn" s4 = teste2(s1) print "Vamos verificar os objetos:n" print "s1 id:#{s1.object_id}, vale #{s1}n" print "s2 id:#{s2.object_id}, vale #{s2}n" print "s3 id:#{s3.object_id}, vale #{s3}n" print "s4 id:#{s4.object_id}, vale #{s4}n" print "sd id:#{sd.object_id}, vale #{sd} (objecto duplicado, id diferente, valor original!)n"Resultado: Vamos verificar os objetos: s1 id:-604854218, vale teste s2 id:-604854218, vale teste sd id:-604854228, vale teste (objeto duplicado, id diferente!) Rodando TESTE1 valor teste, id -604854218 valor TESTE, id -604854348 (aqui tem que ter um id diferente) Vamos verificar os objetos: s1 id:-604854218, vale teste s2 id:-604854218, vale teste s3 id:-604854348, vale TESTE (aqui tem que ter um id diferente) sd id:-604854228, vale teste (objeto duplicado, id diferente!) Rodando TESTE2 valor teste, id -604854218 valor TESTE, id -604854218 Vamos verificar os objetos: s1 id:-604854218, vale TESTE s2 id:-604854218, vale TESTE s3 id:-604854548, vale TESTE s4 id:-604854218, vale TESTE sd id:-604854228, vale teste (objecto duplicado, id diferente, valor original!)Tentando expressar isso graficamente: 31
  32. 32. Figura 3.1: Representa¸˜o de referˆncias aos objetos ca eVamos analisar detalhadamente o que ocorre aqui.ˆ Criei uma vari´vel, s1, que aponta para um objeto tipo String (vari´veis n˜o s˜o objetos, lembre- a a a a se!). Esse objeto foi criado e armazenado em uma determinada ´rea da mem´ria (vejam para onde a o s1 aponta).ˆ Criei uma segunda vari´vel, s2, apontando para o mesmo lugar (mesmo objeto) que s1. aˆ Criei outra vari´vel, sd, duplicando s1, isso ´, criando um novo objeto do tipo de s1 (String), usando a e como ponto de partida o valor referenciado por s1.ˆ Verifiquei os ids das vari´veis. As vari´veis s1 e s2 tem ids idˆnticos, enquanto sd tem um diferente, a a e tudo certo, pois sd aponta para outro objeto.ˆ Criei uma nova vari´vel s3 com o resultado do m´todo teste1, que recebe uma c´pia da re- a e o ferˆncia do objeto, como uma vari´vel local no escopo do m´todo corrente, executa uma opera¸˜o e a e ca criando um novo objeto, cuja referˆncia ´ retornada pelo m´todo e armazenada em s3. Vejam no e e e gr´fico o objeto para onde s3 aponta. aˆ Dentro de teste1 isso fica expl´ ıcito na primeira chamada, onde o id do objeto ´ o mesmo de s1, e e quando retornado (poderia ter retornado direto, sem a vari´vel s, que ia dar na mesma, fiz assim a s´ para ficar mais claro) temos o id do novo objeto. oˆ Criei uma nova vari´vel s4 com o resultado do m´todo teste2, que recebe uma c´pia da referˆncia a e o e do objeto, como uma vari´vel local no escopo do m´todo corrente, e altera diretamente o a e objeto referenciado pela vari´vel, convertendo-o para mai´ sculas, nesse caso. Reparem a u em teste2 como os valores est˜o diferentes, mas os ids s˜o os mesmos. a aˆ A vari´vel s4, ent˜o, aponta para o mesmo objeto originalmente referenciado por s1 e s2, enquanto a a s3 continua sossegada apontando para o objeto criado por teste1, e sd, que foi duplicada no come¸o, c continua a mesma tamb´m. e 32

×