apenas uma figura bonitinha

5.  Mais Sobre Métodos

 

Até agora nós vimos uma porção de métodos diferentes, puts e gets dentre outros (Teste Surpresa: Liste todos os métodos que vimos até agora! Foram dez deles; a resposta está mais embaixo.), mas nós não conversamos realmente sobre o que são métodos. Nós sabemos o que eles fazem, mas não sabemos o que eles são.

Mas, na verdade, isso é o que eles são: coisas que fazem coisas. Se objetos (como strings, inteiros e floats) são os substantivos na linguagem Ruby, os métodos são como os verbos. E, ao contrário do Português (em que há sujeitos indefinidos e outras construções esotéricas), você não pode ter um verbo sem um substantivo para executar o verbo. Mas mesmo o Português trata a ausência de um substantivo como exceção: por exemplo, contar o tempo não é algo que simplesmente acontece; um relógio (ou cronômetro, ou algo parecido) deve fazê-lo. Em Português diríamos: "O relógio conta o tempo". Em Ruby dizemos relogio.tiquetaque (presumindo que relogio é um objeto Ruby, claro). Programadores podem dizer que estamos "chamando o método tiquetaque do relogio," ou que "chamamos tiquetaque no relogio."

E então, você respondeu o quiz? Ótimo. Bem, tenho certeza que você lembrou dos métodos puts, gets e chomp, que acabamos de ver. Você também provavelmente lembrou dos métodos de conversão, to_i, to_f e to_s. No entanto, você descobriu os outros quatro? Pois não eram ninguém menos que nossos velhos amigos da matemática, +, -, * e /!

Como eu estava dizendo, todo método precisa de um objeto. Geralmente é fácil dizer qual objeto está executando o método: é aquilo que vem logo antes do ponto, como no nosso exemplo do relogio.tiquetaque, ou em 101.to_s. Às vezes, no entanto, isso não é tão óbvio; como com os métodos aritméticos. A bem da verdade, 5 + 5 é realmente apenas um atalho para se escrever 5.+ 5. Por exemplo:

puts 'olá '.+ 'mundo'
puts (10.* 9).+ 9
olá mundo
99

Não é muito bonito, então nós nunca mais vamos escrever desse jeito; no entanto, é importante entender o que realmente está acontecendo. (Na minha máquina, isso também me dá um aviso: warning: parenthesize argument(s) for future version. O código ainda rodou sem problemas, mas ele está me dizendo que está com problemas para descobrir o que eu quis dizer, e pedindo para usar mais parênteses no futuro). Isso também nos dá um entendimento mais profundo sobre por que podemos fazer 'porco'*5 mas não 5*'porco': 'porco'*5 está dizendo ao 'porco' para se multiplicar, mas 5*'porco' está pedindo ao 5 que se multiplique. 'porco' sabe como fazer 5 cópias de si mesmo e juntá-las; no entanto, 5 vai ter muito mais dificuldade para fazer 'porco' cópias de si mesmo e juntá-las.

E, claro, nós ainda temos o puts e o gets para explicar. Onde estão seus objetos? Em Português, você pode às vezes omitir o substantivo; por exemplo, se um vilão grita "Morra!", o substantivo implícito é a pessoa com quem ele está gritando. Em Ruby, se dissermos puts 'ser ou não ser', o que eu realmente estou dizendo é self.puts 'ser ou não ser'. Então o que é self? É uma variável especial que aponta para o objeto onde você está. Nós nem sabemos como estar em um objeto ainda, mas até descobrirmos, nós estaremos sempre em um grande objeto que é... o programa inteiro! E para nossa sorte, o programa tem alguns métodos próprios, como puts e gets. Preste atenção:

naoAcreditoQueFizUmNomeDeVariavelTaoGrandeApenasParaGuardarUm3 = 3
puts naoAcreditoQueFizUmNomeDeVariavelTaoGrandeApenasParaGuardarUm3
self.puts naoAcreditoQueFizUmNomeDeVariavelTaoGrandeApenasParaGuardarUm3
3
3

Se você não acompanhou tudo o que aconteceu, não tem problema. A coisa importante para aprender disso tudo é que cada métodos está sendo executado pelo mesmo objeto, mesmo que ele não esteja na sua frente. Se você entender isso, então está preparado.

Métodos Elegantes da String

Vamos aprender alguns métodos divertidos da string. Você não precisa memorizar todos eles; você pode apenas olhar esta página novamente se esquecê-los. Eu só quero mostrar uma pequena parte do que as strings podem fazer. Na verdade, eu mesmo não lembro da metade dos métodos da string—mas não tem problema, pois existem ótimas referências na internet com todos os métodos da string listados e explicados. (Vou mostrar onde encontrá-los no final deste tutorial.) Pra falar a verdade, eu nem quero saber todos os métodos da string; é como saber todas as palavras do dicionário. Eu posso falar Português muito bem sem saber todas as palavras do dicionário... e esse não é exatamente o seu propósito? Para que você não precise saber tudo que está nele?

Então, nosso primeiro método da string é o reverse, que nos dá uma versão ao contrário da string:

var1 = 'pare'
var2 = 'radar'
var3 = 'Voce consegue pronunciar esta frase ao contrario?'

puts var1.reverse
puts var2.reverse
puts var3.reverse
puts var1
puts var2
puts var3
erap
radar
?oirartnoc oa esarf atse raicnunorp eugesnoc ecoV
pare
radar
Voce consegue pronunciar esta frase ao contrario?

Como você pode ver, reverse não inverte a string original; ela apenas faz uma nova versão ao contrário dela. É por isso que var1 ainda é 'pare' mesmo após a chamada a reverse em var1.

Outro método da string é length, que nos diz o número de caracteres (incluindo espaços) na string:

puts 'Qual o seu nome completo?'
nome = gets.chomp
puts 'Você sabia que seu nome possui ' + nome.length + ' caracteres, ' + nome + '?'
Qual o seu nome completo?
Christopher David Pine
#<TypeError: can't convert Fixnum into String>

Uh-oh! Algo deu errado, e parece que isso aconteceu após a linha nome = gets.chomp... Você enxerga o problema? Veja se consegue descobrir.

O problema está em length: ele lhe dá um número, mas queremos uma string. Fácil, vamos colocar um to_s (e cruzar os dedos):

puts 'Qual o seu nome completo?'
nome = gets.chomp
puts 'Você sabia que seu nome possui ' + nome.length.to_s + ' caracteres, ' + nome + '?'
Qual o seu nome completo?
Christopher David Pine
Você sabia que seu nome possui 22 caracteres, Christopher David Pine?

Não, eu não sabia disso. Nota: este é o número de caracteres no meu nome, não o número de letras (conte-as). Eu acho que conseguimos escrever um programa que pergunta seu primeiro nome, nome do meio e sobrenome individualmente e some todos os tamanhos... Ei, por que você não faz isso? Vá em frente, eu espero.

Pronto? Bom! É um programa legal, não é? Depois de mais uns capítulos, entretanto, você vai ficar maravilhado com o que conseguirá fazer.

Existem alguns métodos da string que conseguem mudar a caixa (maiúsculas e minúsculas) da sua string. upcase muda todas as letras minúsculas para maiúsculas, e downcase muda todas as letras maiúsculas para minúsculas. swapcase troca a caixa de todas as letras da string e, finalmente, capitalize é parecido com downcase, exceto que ele troca o primeiro caractere para maiúsculo (se for uma letra).

letras = 'aAbBcCdDeE'
puts letras.upcase
puts letras.downcase
puts letras.swapcase
puts letras.capitalize
puts ' a'.capitalize
puts letras
AABBCCDDEE
aabbccddee
AaBbCcDdEe
Aabbccddee
 a
aAbBcCdDeE

Coisas bem simples. Como você pode ver na linha puts ' a'.capitalize, o método capitalize apenas deixa em maiúsculo o primeiro caractere, não a primeira letra. Também, como vimos anteriormente, durante todas essas chamadas de métodos, letras continuou inalterada. Eu não quero me alongar nesse ponto, mas é importante entender. Existem alguns métodos que mudam o objeto associado, mas ainda não vimos nenhum, e nem iremos ver durante algum tempo.

O último método elegante da string que iremos ver é para formatação visual. O primeiro, center, adiciona espaços no começo e no fim da string para torná-la centralizada. No entanto, assim como você precisa dizer ao puts o que quer que seja impresso, e ao + o que quer que seja adicionado, você precisa dizer ao center a largura total da string a ser centralizada. Então se eu quiser centralizar as linhas de um poema, eu faria assim:

larguraDaLinha = 50
puts(                'Old Mother Hubbard'.center(larguraDaLinha))
puts(               'Sat in her cupboard'.center(larguraDaLinha))
puts(         'Eating her curds an whey,'.center(larguraDaLinha))
puts(          'When along came a spider'.center(larguraDaLinha))
puts(         'Which sat down beside her'.center(larguraDaLinha))
puts('And scared her poor shoe dog away.'.center(larguraDaLinha))
                Old Mother Hubbard                
               Sat in her cupboard                
            Eating her curds an whey,             
             When along came a spider             
            Which sat down beside her             
        And scared her poor shoe dog away.        

Hum... Eu não acho que essa rima é assim, mas sou muito preguiçoso para procurar. (Também, eu queria alinhar a parte do .center larguraDaLinha, por isso acrescentei espaços extra antes das strings. Isso é só por que acho que fica mais bonito assim. Programadores geralmente têm opiniões fortes sobre o que é bonito num programa, e eles geralmente discordam sobre o assunto. Quanto mais você programar, mais vai descobrir seu próprio estilo). Falando em ser preguiçoso, a preguiça nem sempre é algo ruim na programação. Por exemplo, viu como eu guardei a largura do poema numa variável larguraDaLinha? Fiz isso pois se quiser tornar o poema mais largo mais tarde, só precisarei mudar a primeira linha do programa, ao invés de todas as linhas que são centralizadas. Com um poema muito longo, isso poderia me poupar um bom tempo. Esse tipo de preguiça é na verdade uma virtude na programação.

Então, em relação à centralização... você deve ter percebido que não está tão bonito quanto um processador de texto teria feito. Se você realmente quer centralização perfeita (e talvez uma fonte melhor), então você deveria apenas usar um processador de texto! Ruby é uma ferramenta maravilhosa, mas nenhuma ferramenta é a ferramenta certa para qualquer trabalho.

Os outros dois métodos de formatação da string são ljust e rjust, que fazem o texto justificado à esquerda e justificado à direita. Eles são parecidos com o center, exceto que eliminam os espaços em branco da string do lado direito e esquerdo, respectivamente. Vamos ver os três em ação:

larguraDaLinha = 40
str = '--> text <--'
puts str.ljust  larguraDaLinha
puts str.center larguraDaLinha
puts str.rjust  larguraDaLinha
puts str.ljust (larguraDaLinha/2) + str.rjust (larguraDaLinha/2)
--> text <--                            
              --> text <--              
                            --> text <--
--> text <--                --> text <--

Umas Coisinhas Para Tentar

• Escreva um programa do Chefe Zangado. Ele deve perguntar o que você quer de forma rude. Qualquer que seja a sua resposta, o Chefe Zangado vai gritar de volta para você, e então despedi-lo. Por exemplo, se você digitar Eu quero um aumento., ele deve gritar de volta O QUE VOCÊ QUER DIZER COM "EU QUERO UM AUMENTO."?!?  VOCÊ ESTÁ DESPEDIDO!!

• Eis aqui algo para você fazer para brincar um pouco mais com center, ljust e rjust: Escreva um programa que irá mostrar um Índice de forma que fique parecido com:

                Tabela de Conteúdo                
                                                  
Capítulo 1:  Números                      página 1
Capítulo 2:  Letras                      página 72
Capítulo 3:  Variáveis                  página 118

Matemática Avançada

(Esta seção é totalmente opcional. Ela assume um certo nível de conhecimento matemático. Se você não estiver interessado, você pode ir direto para o Controle de Fluxo sem nenhum problema. No entanto, uma breve passada pela seção de Números Aleatórios pode ser útil.)

Não há tantos métodos nos números quanto nas strings (apesar de eu ainda não ter decorado todos). Aqui, iremos olhar o resto dos métodos de aritmética, um gerador de números aleatórios e o objeto Math, com seus métodos trigonométricos e transcendentais.

Mais Aritimética

Os outros dois métodos aritméticos são ** (exponenciação) e % (módulo). Então se você quisesse dizer "cinco ao quadrado" em Ruby, você escreveria 5**2. Você também pode usar floats para seu expoente, então se você quiser a raiz quadrada de 5, você pode escrever 5**0.5. O método módulo lhe dá o resto da divisão por um número. Então, por exemplo, se eu divido 7 por 3, eu tenho 2 com resto 1. Vamos vê-los em ação num programa:

puts 5**2
puts 5**0.5
puts 7/3
puts 7%3
puts 365%7
25
2.23606797749979
2
1
1

Pela última linha, aprendemos que um ano (não-bissexto) tem um certo número de semanas, mais um dia. Então se seu aniversário caiu numa terça-feira este ano, ele será numa quarta-feira no ano que vem. Você também pode usar floats com o método módulo. Basicamente, ele funciona da única maneira razoável que consegue... Mas eu vou deixar você brincar um pouco com isso.

Tem um último método para ser mencionado antes de vermos o gerador de números aleatórios: abs. Ele simplesmente pega o valor absoluto de um número:

puts((5-2).abs)
puts((2-5).abs)
3
3

Números Aleatórios

Ruby vem com um gerador de números aleatórios bem legal. O método que escolhe aleatoriamente um número é o rand. Se você chamar rand simplesmente assim, você vai ter um float maior ou igual a 0.0 e menor que 1.0. Se você der um inteiro (5 por exemplo) para o rand, ele vai te dar um inteiro maior ou igual a 0 e menor que 5 (então são cinco números possíveis, de 0 até 4).

Vamos ver o rand em ação. (Se você recarregar esta página, estes números vão mudar a cada vez. Você sabia que eu estou realmente rodando estes programas, não sabia?)

puts rand
puts rand
puts rand
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(1))
puts(rand(1))
puts(rand(1))
puts(rand(99999999999999999999999999999999999999999999999999999999999))
puts('O homem do tempo disse que existe '+rand(101).to_s+'% de chance de chover,')
puts('mas você não pode nunca confiar num homem do tempo.')
0.533099438199271
0.692927743758217
0.940976910494312
35
25
43
0
0
0
43268570703742641064840128301077341089498686011220522458380
O homem do tempo disse que existe 42% de chance de chover,
mas você não pode nunca confiar num homem do tempo.

Perceba que eu usei rand(101) para conseguir os números de 0 até 100, e que rand(1) sempre retorna 0. Não entender o intervalo dos possíveis valores retornados é o maior erro que eu vejo as pessoas cometerem ao usar rand; mesmo programadores profissionais; mesmo em produtos terminados que você pode comprar na loja. Eu inclusive tive um tocador de CD que, se configurado para "Tocar Aleatoriamente", iria tocar todas as músicas menos a última... (Eu imagino o que aconteceria se eu colocasse um CD com apenas uma música nele?)

As vezes você pode querer que rand retorne os mesmos números aleatórios na mesma sequência em duas execuções diferentes do seu programa. (Por exemplo, uma vez eu estava usando números aleatórios gerados para criar um mundo gerado aleatoriamente num jogo de computador. Se eu encontrasse um mundo que eu realmente gostasse, talvez eu quisesse jogar nele novamente, ou mandá-lo para um amigo). Para isso, você precisa configurar a semente, que você consegue fazer com srand. Desta forma:

srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts ''
srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
24
35
36
58
70

24
35
36
58
70

Ele fará a mesma coisa sempre que você alimentá-lo com a mesma semente. Se você quer voltar a ter números diferentes (como acontece quando você nunca usa srand), então apenas chame srand 0. Isso alimenta o gerador com um número realmente estranho, usando (dentre outras coisas) a hora atual do seu computador, com precisão de milisegundos.

O Objeto Math

Finalmente, vamos olhar para o objeto Math. Vamos começar de uma vez:

puts(Math::PI)
puts(Math::E)
puts(Math.cos(Math::PI/3))
puts(Math.tan(Math::PI/4))
puts(Math.log(Math::E**2))
puts((1 + Math.sqrt(5))/2)
3.14159265358979
2.71828182845905
0.5
1.0
2.0
1.61803398874989

A primeira coisa que você percebeu foi provavelmente a notação do ::. Explicar o operador de escopo (que é o que ele é) está um pouco além do, uh... escopo deste tutorial. Não é nenhum trocadilho. Eu juro. Basta dizer que você pode usar Math::PI exatamente da forma como você espera.

Como você pode ver, Math tem todas as coisas que você esperaria que uma calculadora científica decente tivesse. E, como sempre, os floats estão realmente perto de serem as respostas certas.

Então vamos entrar no fluxo!

 

© 2003-2015 Chris Pine