Introdução à Linguagem Ruby
-
Upload
nicola-zagari -
Category
Technology
-
view
7.666 -
download
6
description
Transcript of Introdução à Linguagem Ruby
Introdução ao Ruby
Eduardo Nicola F. Zagari
SumárioInstalação, Primeiros Passos, Variáveis e Escopo
Tipos Básicos
Constantes
Módulos
Operadores Condicionais e Loops
Operadores de Loop
Instalação do RubyLinux (Ubuntu):
Windows:
http://www.ruby-lang.org/en/downloads (Ruby One-Click Installer)
(instale em um diretório sem espaços no nome e inclua o subdiretório <$RUBY>\bin ao path do sistema operacional)
Mac:
$> sudo apt-get
$> port install
Documentação do Ruby
http://apidock.com/ruby
http://www.ruby-doc.org/core/
Primeiros Passos
irb: Interactive Ruby - Funciona como um console/terminal, avaliando cada linha inserida e mostrando o resultado imediatamente
Outra forma de executar os comandos é colocá-los em um arquivo “.rb” e chamar o comando “ruby”, passando o arquivo como parâmetro da linha de comando
Primeiros Passos$> irb>> 1+1 => 2
>> def soma a, b>> a+b>> end=> nil>> soma 1, 2=> 3
equivalente a: >> def soma(a, b)>> a+b;?> end=> nil>> soma(1,2)=> 3
Syntax Sugar:equivalente a 1.+(1)
Estão disponíveis os operadores tradicionais: +, -, /, * e ** (potência)
Primeiros Passos
>> resultado = 4 ** 2=> 16>> puts(resultado)16=> nil
puts é o método usado para imprimir valores no stdout e nil é o objeto nulo do Ruby
Ruby possui tipagem: - implícita (não precisa de declaração) - forte (não se pode misturar tipos diferentes) - dinâmica (pode-se inserir/alterar métodos/comportamentos em objetos)
Primeiros Passos>> 1.class=> Fixnum>> self.class=> Object>> [].class=> Array>> {}.class=> Hash>> "a".class=> String>> 1.1.class=> Float>> 99999999999999999.class=> Bignum
- Tudo é objeto, todo objeto pertence a uma classe e todas as classes descendem de Object- self indica o objeto atual
Primeiros Passos
>> 1.methods=> ["inspect", "%", "<<", "singleton_method_added", "&", "clone", "method", ">>", "round", "public_methods", "rdiv", "instance_variable_defined?", "divmod", "equal?", "freeze", "integer?", "chr", "*", "+", "to_i", "methods", "respond_to?", "numerator", "-", "upto", "between?", "prec", "truncate", "/", "dup", "instance_variables", "rpower", "taguri", "__id__", "modulo", "object_id", "succ", "|", "eql?", "zero?", "id", "~", "taguri=", "to_f", "singleton_methods", "send", "prec_i", "taint", "step", "to_int", "frozen?", "instance_variable_get", "__send__", "instance_of?", "^", "remainder", "to_yaml_style", "to_a", "+@", "nonzero?", "-@", "type", "**", "floor", "<", "protected_methods", "instance_eval", "<=>", "lcm", "==", "prec_f", "power!", "quo", ">", "display", "===", "downto", "id2name", "size", "instance_variable_set", "kind_of?", "extend", "abs", ">=", "next", "to_s", "<=", "denominator", "coerce", "hash", "ceil", "class", "to_yaml", "tainted?", "=~", "private_methods", "gcdlcm", "div", "to_yaml_properties", "nil?", "untaint", "gcd", "times", "to_sym", "soma", "[]", "to_r", "is_a?"]
Object tem o método methods, que retorna um array com todos os métodos disponíveis da classe:
Primeiros Passos
>> class Fixnum>> def +(other)>> self - other>> end>> end=> nil>> 1+5=> -4
Open Classes: podemos abrir todas as classes e alterar seus comportamentos! Isto é bastante útil, mas é bastante perigoso também!
Variáveis de escopo>> 1 + "2"TypeError: String can't be coerced into Fixnum from (irb):22:in `-' from (irb):22:in `+' from (irb):22
Em Ruby não é preciso declarar uma variável, pois ele usa tipagem implícita, mas não tipagem fraca!
O escopo de variáveis não é definido por palavras-chave e sim por símbolos:
Símbolo Descriçãonome Variável local@nome Variável de instância@@nome Variável de classe$nome Variável global
Tipos Básicos
Blocos de código
Procs
Números
Valores booleanos
Strings
Blocos de código>> arr = [1,2,3,4]=> [1, 2, 3, 4]>> arr.each { |val|?> print "#{val}\n" }1234=> [1, 2, 3, 4]
Usados para iterar em coleções, personificar comportamento de métodos e definir DSLs
Podem ser definidos pelos símbolos “{“ e “}” ou por “do” e “end” e podem receber parâmetros logo depois de abertos usando “|” para demarcar o início e fim da lista de parâmetros
Blocos de código
>> arr.each_with_index do |val, idx|?> print "Posicao #{idx} valor #{val}\n";?> endPosicao 0 valor 1Posicao 1 valor 2Posicao 2 valor 3Posicao 3 valor 4=> [1, 2, 3, 4]
Usando “do” e “end”
Blocos de código>> valor = 1=> 1>> arr.each do |val|?> valor += val;?> end=> [1, 2, 3, 4]>> valor=> 11
Closure: bloco de código com variáveis visíveis do seu contexto
Blocos de código>> valor = 1=> 1>> def iterar >> arr = [1,2,3,4]>> arr.each do |val|?> valor += val;?> end>> end=> nil>> iterarNoMethodError: undefined method `+' for nil:NilClass from (irb):25:in `iterar' from (irb):24:in `each' from (irb):24:in `iterar' from (irb):28
Se for utilizado um método, teremos um erro, pois ele não “aponta” para as variáveis do contexto em que foi definido, como o faz a closure
Blocos de código>> def recebe_proc_e_passa_parametro>> if block_given?>> yield>> else?> puts "Voce precisa passar um bloco para este metodo\n">> end>> end=> nil>> recebe_proc_e_passa_parametroVoce precisa passar um bloco para este metodo=> nil>> recebe_proc_e_passa_parametro { print "dentro do bloco\n" }dentro do bloco=> nil
Blocos de código podem ser passados como parâmetros para métodos
Blocos de código>> def recebe_proc_e_passa_parametro>> if block_given?>> yield(23)>> else?> puts "Voce precisa passar um bloco para este metodo\n">> end>> end=> nil>> recebe_proc_e_passa_parametro do |par|?> puts "Recebi #{par} dentro desse bloco\n">> endRecebi 23 dentro desse bloco=> nil
Pode-se passar parâmetros para blocos recebidos nos métodos
Procs>> def recebe_proc(&block)>> if block>> block.call>> end>> end=> nil>> recebe_proc=> nil>> recebe_proc { print "este bloco vai se tornar uma proc, pois vai ser atribuido a uma variavel no metodo"}=> este bloco vai se tornar uma proc, pois vai ser atribuido a uma variavel no metodo=> nil
Procs se parecem com blocos e com closures, mas podem ser armazenados em uma variável. No entanto, são mais “caros”.
Procs>> p = Proc.new { print "este bloco vai se tornar uma proc, pois estah sendo atribuido a uma variavel\n"}=> #<Proc:0x00551d4c@(irb):11>>> p.calleste bloco vai se tornar uma proc, pois estah sendo atribuido a uma variavel=> nil
>> p1 = lambda do ?> print "este bloco vai se tornar uma proc, pois estah sendo atribuido a uma variavel\n">> end=> #<Proc:0x00543904@(irb):13>>> p1.calleste bloco vai se tornar uma proc, pois estah sendo atribuido a uma variavel=> nil
Criação de Proc utilizando construtor da classe Proc
Criação de Proc utilizando a palavra-chave lambda
Procs>> p = Proc.new { print "a" }=> #<Proc:0x0053ad90@(irb):17>
>> p.methods.sort=> ["==", "===", "=~", "[]", "__id__", "__send__", "arity", "binding", "call", "class", "clone", "display", "dup", "eql?", "equal?", "extend", "freeze", "frozen?", "hash", "id", "inspect", "instance_eval", "instance_of?", "instance_variable_defined?", "instance_variable_get", "instance_variable_set", "instance_variables", "is_a?", "kind_of?", "method", "methods", "nil?", "object_id", "private_methods", "protected_methods", "public_methods", "recebe_proc", "respond_to?", "send", "singleton_methods", "taguri", "taguri=", "taint", "tainted?", "to_a", "to_proc", "to_s", "to_yaml", "to_yaml_properties", "to_yaml_style", "type", "untaint"]
Proc é uma classe, descendente de Object, e possui vários métodos
ProcsMétodo Descrição
call
[]
arity
binding
Utilizado para executar o proc, os parâmetros que forem definidos no bloco são passados como parâmetros para call
Alias para o método call, ou seja, pode-se executar um proc com a sintaxe: p[parâmetros]
Informa o número de parâmetros definidos nesse proc
Retorna a Binding correspondente ao local onde foi definido o bloco de código que deu origem a esse proc
Números
Classe Descrição
Fixnum
Bignum
Float
Representa inteiros de -1073741824 a 1073741823
Representa inteiros fora do intervalo da classe Fixnum
Representa números em ponto flutuante
Números>> i = 1=> 1>> i.class=> Fixnum>> i1 = 1.1=> 1.1>> i1.class=> Float>> i2 = 111_222_333=> 111222333>> i2.class=> Fixnum>> i3=999999999999999999999=> 999999999999999999999>> i3.class=> Bignum
Valores Booleanos
>> def testa_valor(val)>> if val>> print "#{val} eh considerado verdadeiro pelo Ruby\n">> else?> print "#{val} eh considerado falso pelo Ruby\n">> end>> end=> nil
Operadores booleanos: ==, >, <, >= e <=
Expressões booleanas podem ainda ser combinadas com os operadores: && (and) e || (or)
Valores Booleanos
>> testa_valor truetrue eh considerado verdadeiro pelo Ruby=> nil>> testa_valor falsefalse eh considerado falso pelo Ruby=> nil>> testa_valor "asdf"asdf eh considerado verdadeiro pelo Ruby=> nil>> testa_valor nil eh considerado falso pelo Ruby=> nil
“false” e “nil” são falsos“true” e tudo mais é verdadeiro
StringsSímbolo Descrição
aspas
apóstrofes
<<MARCADOR
%Q{ }
%q{ }
String simples com expansão de variáveis
String simples sem expansão de variáveis
String multilinha com expansão de variáveis
String multilinha com expansão de variáveis
String multilinha sem expansão de variáveis
Strings>> a = "texto"=> "texto">> b = 'texto'=> "texto">> c = "texto\nsegunda linha"=> "texto\nsegunda linha">> d = 'texto\nmesma linha'=> "texto\\nmesma linha">> e = "a = #{a} - eh assim que se utiliza expansao de variaveis"=> "a = texto - eh assim que se utiliza expansao de variaveis">> f = <<__ATEH_O_FINALesta ehuma Stringbem grande e soh terminaquando encontrar o marcador __ATEH_O_FINALno inicio de uma linha__ATEH_O_FINAL=> "esta eh\numa String\nbem grande e soh termina\nquando encontrar o marcador __ATEH_O_FINAL\nno inicio de uma linha\n"
Strings
g
>> g = %Q{Esta tambem eh uma Stringcom mais de uma linhae tambem suporta #{a}expansao de variaveis}=> "Esta tambem\neh uma String\ncom mais de uma linha\ne tambem suporta texto\nexpansao de variaveis\n"
>> h = %q{Jahestaque tambem eh multi-linhanao suporta #{a}expansao de variaveis}=> "Jah\nesta\nque tambem eh multi-linha\nnao suporta \#{a}\nexpansao de variaveis"
ConstantesIntervalos numéricos
Arrays
Hashes
Símbolos
Expressões regulares
Classes e métodos
Métodos de classe
Constantes>> variavel = 1=> 1>> variavel = "asdf"=> "asdf"
>> CONSTANTE = "asdf"=> "asdf">> CONSTANTE = 1(irb):62: warning: already initialized constant CONSTANTE=> 1>> Constante = 2=> 2>> Constante = 5(irb):64: warning: already initialized constant Constante=> 5
Não existem, mas existe um padrão que diz que variáveis com primeira letra maíuscula são constantes
Intervalos Numéricos>> a = 1..10=> 1..10>> b = 1...10=> 1...10
>> a.each do |v|?> print "#{v} ">> end1 2 3 4 5 6 7 8 9 10 => 1..10
>> b.each do |v|?> print "#{v} ">> end1 2 3 4 5 6 7 8 9 => 1...10
Dois tipos: - inclusivo: .. - exclusivo: ...
Arrays
>> arr = [ ] => []
>> arr = Array.new=> []
>> arr = %w{ a b c }=> ["a", "b", "c"]
No Ruby, não são tipados!Mas além das 2 formas de declarar arrays genéricos, existe uma forma especial para declarar arrays que contêm apenas strings
Arrays>> arr.methods=> ["select", "[]=", "inspect", "compact", "<<", "&", "clone", "method", "last", "public_methods", "partition", "empty?", "delete_if", "instance_variable_defined?", "equal?", "freeze", "each_index", "*", "grep", "+", "sort!", "assoc", "to_ary", "methods", "respond_to?", "-", "reject", "push", "insert", "reverse!", "dup", "delete", "instance_variables", "taguri", "concat", "member?", "__id__", "object_id", "pack", "reverse_each", "|", "find", "eql?", "join", "collect!", "rassoc", "each_with_index", "id", "at", "compact!", "taguri=", "singleton_methods", "index", "collect", "send", "reject!", "flatten", "all?", "slice", "taint", "pop", "length", "entries", "instance_variable_get", "transpose", "frozen?", "include?", "__send__", "instance_of?", "to_yaml_style", "detect", "to_a", "indexes", "uniq", "zip", "map!", "type", "fetch", "protected_methods", "instance_eval", "map", "<=>", "values_at", "rindex", "any?", "==", "display", "===", "shift", "size", "sort", "instance_variable_set", "clear", "min", "kind_of?", "extend", "indices", "find_all", "to_s", "each", "class", "slice!", "first", "hash", "flatten!", "to_yaml", "tainted?", "=~", "delete_at", "replace", "inject", "private_methods", "nitems", "reverse", "to_yaml_properties", "nil?", "untaint", "unshift", "sort_by", "fill", "max", "is_a?", "uniq!", "[]", "yaml_initialize"]
ArraysMétodo Descrição
select
[]=
[]
last
empty?
equal?
Recebe um bloco e retorna um array contendo todos os elementos para os quais o bloco retornou true
Define o valor de uma posição do array
Retorna o valor da posição passada como parâmetro
Retorna o último item do array
Retorna verdadeiro se o array estiver vazio
Compara com outro array
ArraysMétodo Descrição
each_index
sort
sort!
+
-
push ou <<
Recebe um bloco e passa apenas os índices do array para o bloco
Retorna um novo array contendo os itens deste ordenados
Similar ao sort, mas altera o array de origem
Concatena 2 arrays, criando um novo com os itens de ambos
Cria um novo array com os itens do primeiro não contidos no segundo
Adiciona um item no final do array (append)
ArraysMétodo Descrição
pop
find
clear
shift
first
inject
Retorna o último item e o remove do array
Recebe um bloco com um parâmetro e retorna o primeiro item para o qual o bloco retornar verdadeiro
Remove todos os itens do array
Retorna o primeiro item e o remove do array
Retorna o primeiro item do array
Recebe um valor inicial e um bloco com dois parâmetros: o valor atual e o item atual do array, retornando o resultado
da operação realizada no bloco
Arrays>> arr = %w{ a b c }=> ["a", "b", "c"] >> arr << “d”=> ["a", "b", "c", "d"] >> arr.select {|x| x!='a'}=> ["b", "c", "d"]
>> arr = [1, 2, 3, 4, 5, 6]=> [1, 2, 3, 4, 5, 6]
>> arr.inject(0) do |val, it|?> val + it>> end=> 21
Exemplos
Arrays>> lista = ["4", "um", "cinco", "bla"]=> ["4", "um", "cinco", "bla"]>> lista.each do |item|?> puts item>> end4umcincobla=> ["4", "um", "cinco", "bla"]>> novo = lista.map do |item|?> item.upcase>> end=> ["4", "UM", "CINCO", "BLA"]>> novo.inspect=> "[\"4\", \"UM\", \"CINCO\", \"BLA\"]"
each: chama o bloco associado para cada um dos itens, passando o item como parâmetro
map (ou collect): coleta os retornos de todas as chamadas do
bloco associado
Arrays>> def parametros_variaveis(param1, param2, *arr)>> if arr>> arr.each do |v|?> print "#{v.class} - #{v}\n">> end>> end>> end=> nil>> parametros_variaveis 1, 2=> []>> parametros_variaveis 1, 2, 3, "asdf", :simb, :a => "teste", :arr => %w{a b c} Fixnum - 3String - asdfSymbol - simbHash - arrabcateste=> [3, "asdf", :simb, {:arr=>["a", "b", "c"], :a=>"teste"}]
Em Ruby, é possível criar métodos com uma lista variável de parâmetros usando-se arrays
O operador *, neste caso, é chamado de splat
Hashes>> h = { 1 => "asdf", "b" => 123 }=> {"b"=>123, 1=>"asdf"}
>> h1 = { } => {}
>> h2 = Hash.new=> {}
Hashes são coleções do tipo chave => valor
Símbolo “=>”
Duas formas de declaração: atalho { } e o construtor da classe Hash
Hashes>> h.methods.sort=> ["==", "===", "=~", "[]", "[]=", "__id__", "__send__", "all?", "any?", "class", "clear", "clone", "collect", "default", "default=", "default_proc", "delete", "delete_if", "detect", "display", "dup", "each", "each_key", "each_pair", "each_value", "each_with_index", "empty?", "entries", "eql?", "equal?", "extend", "fetch", "find", "find_all", "freeze", "frozen?", "grep", "has_key?", "has_value?", "hash", "id", "include?", "index", "indexes", "indices", "inject", "inspect", "instance_eval", "instance_of?", "instance_variable_defined?", "instance_variable_get", "instance_variable_set", "instance_variables", "invert", "is_a?", "key?", "keys", "kind_of?", "length", "map", "max", "member?", "merge", "merge!", "method", "methods", "min", "nil?", "object_id", "parametros_variaveis", "partition", "private_methods", "protected_methods", "public_methods", "rehash", "reject", "reject!", "replace", "respond_to?", "select", "send", "shift", "singleton_methods", "size", "sort", "sort_by", "store", "taguri", "taguri=", "taint", "tainted?", "to_a", "to_hash", "to_s", "to_yaml", "to_yaml_properties", "to_yaml_style", "type", "untaint", "update", "value?", "values", "values_at", "yaml_initialize", "zip"]
HashesMétodo Descrição
[]
[]=
each
each_key
has_key?
Retorna o valor da chave passada como parâmetro
Atribui o valor da chave
Executa um bloco com dois argumentos para cada posição do mapa
Executa um bloco com um argumento (a chave) para cada posição do mapa
Retorna verdadeiro se a chave existe no mapa
HashesMétodo Descrição
has_value?
default=
default_proc
delete
Retorna verdadeiro se o valor corresponde a alguma dos valores do mapa
Possibilita configurar qual valor o mapa vai retornar quando for buscado o valor para uma chave inexistente
Idem a default=, mas executa um bloco para criar o valor para as novas chaves
Remove o item correspondente à chave indicada do mapa, retornando o valor da classe
Símbolos
São nomes iniciados com “:”
São muito utilizados como chaves em hashes ou como rótulos para alguma coisa
São como strings, mas consomem menos recursos do que elas
“to_sym” : transforma strings em símbolos
Expressões RegularesExpressões regulares fazem parte da linguagem no Ruby
Existem 3 formas de declarar expressões regulares em Ruby:
>> er = /(.*?) .*/=> /(.*?) .*/>> er = %r{(.*?) .*}=> /(.*?) .*/>> er = Regexp.new "(.*?) .*"=> /(.*?) .*/
Expressões Regulares>> er = /^[0-9]/=> /^[0-9]/>> "123" =~ er=> 0>> er =~ "123"=> 0>> er =~ "abc"=> nil>> er !~ "123"=> false>> er !~ "abc"=> true>> mt = /(..)\/(..)\/(....)/.match("08/04/2010")=> #<MatchData:0x53d5cc>>> mt.length=> 4
A classe Regexp disponibiliza diversos métodos e operadores para facilitar a operação com ERs
Expressões Regulares>> mt[0]=> "08/04/2010">> mt[1]=> "08">> mt[2]=> "04">> mt[3]=> "2010">> todo, dia, mes, ano = *(/(..)\/(..)\/(....)/.match("08/04/2010"))=> ["08/04/2010", "08", "04", "2010"]>> todo=> "08/04/2010">> dia=> "08">> mes=> "04">> ano=> "2010"
Expressões Regulares>> "Zagari".gsub(/ri/,"rI")=> "ZagarI"
>> er = /.*/=> /.*/>> er.methods=> ["inspect", "clone", "method", "public_methods", "instance_variable_defined?", "equal?", "freeze", "match", "methods", "respond_to?", "casefold?", "dup", "instance_variables", "taguri", "options", "__id__", "object_id", "eql?", "~", "parametros_variaveis", "id", "taguri=", "singleton_methods", "send", "taint", "frozen?", "instance_variable_get", "__send__", "instance_of?", "to_yaml_style", "kcode", "to_a", "type", "protected_methods", "instance_eval", "==", "display", "===", "instance_variable_set", "kind_of?", "extend", "to_s", "hash", "class", "to_yaml", "tainted?", "=~", "private_methods", "to_yaml_properties", "source", "nil?", "untaint", "is_a?"]
Expressões RegularesMétodo Descrição
=~
!~
match
Procura pela expressão regular no texto e retorna o índice em que ela foi encontrada
Informa se existe uma ocorrência da expressão regular no texto
Retorna um objeto do tipo MatchData, que contém ponteiros para os locais onde cada grupo da expressão regular foi
encontrado
Mundo Orientado a Objetos>> pessoa = Object.new()=> #<Object:0x553c14>>> def pessoa.fala()>> puts "Sei falar">> end=> nil>> pessoa.fala()Sei falar=> nil>> def pessoa.troca(roupa, lugar='banheiro')>> puts "trocando de #{roupa} no #{lugar}">> end=> nil>> pessoa.troca("camiseta")trocando de camiseta no banheiro=> nil
Tudo em Ruby é objeto!E Ruby é uma linguagem dinâmica!
Os últimos argumentos podem ter um valor padrão, tornando-se opcionais
Classes>> class Pessoa>> def fala>> puts "Sei Falar">> end>> ?> def troca(roupa, lugar="banheiro")>> puts "trocando de #{roupa} no #{lugar}" >> end>> end=> nil>> p = Pessoa.new=> #<Pessoa:0x50ef88>>> p.class=> Pessoa>> p.class.class=> Class
Classes servem para que se crie objetos com alguns métodos já inclusos
Classes são também objetos!
Classes
>> class Conta>> def transfere_para(destino, quantia)>> debita quantia # mesmo que self.debita(quantia)>> destino.deposita quantia>> end>> end=> nil
Um método pode chamar outro método do próprio objeto via “self” (equivalente ao this)
Toda chamada de método é sempre uma mensagem enviada a algum objeto
Classes>> class Professor>> def ensina(aluno)>> def aluno.escreve>> "Sei escrever!">> end>> end>> end=> nil>> juca = Aluno.new=> #<Aluno:0x31cb80>>> juca.respond_to? :escreve=> false>> zagari = Professor.new=> #<Professor:0x3007f0>>> zagari.ensina juca=> nil>> juca.escreve=> "Sei escrever!"
Dinamismo ao extremo: métodos que definem métodos em outros objetos
Atributos>> class Pessoa>> def muda_nome(novo_nome)>> @nome = novo_nome>> end>> def diz_nome>> "meu nome eh #{@nome}">> end>> end=> nil
>> p = Pessoa.new=> #<Pessoa:0x58ad18>>> p.muda_nome "Joao"=> "Joao">> p.diz_nome=> "meu nome eh Joao"
Variáveis de instância: são sempre privadas (encapsulamento) começam com @
Construtor>> class Pessoa >> def initialize>> puts "Criando nova Pessoa">> end>> end=> nil>> Pessoa.newCriando nova Pessoa=> #<Pessoa:0x567f84>
>> class Pessoa>> def initialize(nome)>> @nome = nome>> end>> end=> nil>> joao = Pessoa.new("Joao”)=> #<Pessoa:0x57515c @nome="Joao">
Método “initialize”: código executado na criação de um objeto
Os “initialize” são métodos privados e podem receber parâmetros
Acessores e Modificadores>> class Pessoa>> def nome #acessor>> @nome>> end>> def nome=(novo_nome)>> @nome = novo_nome>> end>> end=> nil>> pessoa = Pessoa.newCriando nova Pessoa=> #<Pessoa:0x54cc48>>> pessoa.nome=("Jose")=> "Jose">> puts pessoa.nomeJose=> nil>> pessoa.nome = "Maria"=> "Maria"
Método acessor
Método modificador
Syntax Sugarnão é uma simples atribuição
Métodos de Classe>> class Pessoa>> # ...>> end=> nil>> def Pessoa.pessoas_no_mundo>> 100>> end=> nil>> Pessoa.pessoas_no_mundo=> 100
>> class Pessoa>> def self.pessoa_no_mundo>> 100>> end>> # ...?> end=> nil
Se classes são objetos, podemos
definir métodos de classe como em qualquer outro
objeto
“Idiomismo” para se definir os métodos de classe dentro
da própria definição da classe, onde self aponta para
o próprio objeto classe
Métodos de Classe>> class Pessoa>> attr_accessor :nome>> end=> nil
>> p = Pessoa.new=> #<Pessoa:0x58fc00>
>> p.nome = "Joaquim"=> "Joaquim"
>> puts p.nomeJoaquim=> nil
Existem métodos de classe que auxiliam
na criação de métodos
(metaprogramação) acessores e
modificadores:
attr_accessorattr_readerattr_writer
Mais OO>> class Animal>> def come>> "comendo">> end>> end=> nil>> class Pato < Animal>> def quack>> "Quack!">> end>> end=> nil>> pato = Pato.new=> #<Pato:0x555dac>>> pato.come=> "comendo"
Ruby tem suporte à herança simples de
classes
Mais OO>> class PatoNormal>> def faz_quack>> "Quack!">> end>> end=> nil>> class PatoEstranho>> def faz_quack>> "Queeeeck!">> end>> end=> nil>> class CriadorDePatos>> def castiga(pato)>> pato.faz_quack>> end>> end=> nil
Como a tipagem em Ruby não é
explícita, não precisamos declarar quais são os tipos dos atributos e/ou
parâmetros
Mais OO>> pato1 = PatoNormal.new=> #<PatoNormal:0x5332e8>>> pato2 = PatoEstranho.new=> #<PatoEstranho:0x52ed10>>> c = CriadorDePatos.new=> #<CriadorDePatos:0x529cfc>>> c.castiga(pato1)=> "Quack!">> c.castiga(pato2)=> "Queeeeck!"
Duck Typing:Para o criador de
patos, não interessa que objeto será passado como parâmetro, basta que ele saiba grasnar.
“If it walks like a duck and quacks like a duck, I would call it a duck.”
Módulos>> module Util>> module Validadores>>>> class ValidadorDeCpf>> # ...?> end>>>> class ValidadorDeRg>> # ...?> end>> end>> end=> nil
>> validador = Util::Validadores::ValidadorDeCpf=> Util::Validadores::ValidadorDeCpf
Módulos podem ser usados como namespaces
(organizadores de classes)
Módulos>> module Comentavel>> def comentarios>> @comentarios ||= []>> end>> def recebe_comentario(comentario)>> self.comentario << comentario>> end>> end=> nil>> class Revista>> include Comentavel>> # ...?> end=> Revista>> revista = Revista.new=> #<Revista:0x31d3a0>>> revista.recebe_comentario("muito ruim!")=> ["muito ruim!"]>> puts revista.comentariosmuito ruim!=> nil
Ou como mixins, conjunto de métodos a ser incluso em outras
classes.
Se o método extend for utilizado, os métodos
do módulo estarão disponíveis para a
classe e não para suas instâncias
Operadores condicionais
if / elsif / else / end
case / when / else / end
Operadores condicionais>> a = 0=> 0>> if a == 0>> print "zero">> elsif a == 1>> print "um">> else?> print "nao sei que numero eh este">> endzero=> nil
>> b = 5 if a != 1=> 5
O “if” pode também ser utilizado no final de uma instrução
Não é necessário o uso do “then”
If / elsif / else / end
Operadores condicionais>> a = 1=> 1>> unless a == 0>> print "nao eh zero\n">> else?> print "a eh zero\n">> endnao eh zero=> nil>> b = 6 unless b=> nil>> b = 7 unless b=> nil
Deve-se tomar cuidado com o uso do unless na definição de valores de variáveis se o valor esperado delas for um valor booleano
O unless é um “facilitador” para um “if not”
Também pode ser utilizado no final de uma instrução
unless / else / end
Operadores condicionais>> a = 5=> 5>> case a>> when 1..3>> puts "a entre 1 e 3\n">> when 4>> puts "a = 4\n">> else?> puts "nenhuma das anteriores\n">> endnenhuma das anteriores=> nil
case é um “facilitador” para uma sequência de elsif
case / when / else / end
Operadores condicionais>> a = "b"=> "b">> case a>> when "a">> puts "a\n">> when "b">> puts "b\n">> else?> puts "outra letra\n">> endb=> nil Só não é possível misturar objetos
Pode ser utilizado com qualquer tipo de objeto e não apenas com números
Loopswhile
for
until
begin
loop
Padrões importantes
Operadores de loopOperador Descrição
break
next
return
redo
Sai do loop atual
Executa o próximo passo do loop
Sai do loop e do método atual
Reinicia o loop atual
Loops>> i = %w{a b c d e f}=> ["a", "b", "c", "d", "e", "f"]>> while b = i.pop>> puts b>> endfedcba=> nil# Isto é apenas um exemplo (use “each”!)
Permite o controle da condição do loop, podendo ser utilizado com qualquer condição booleana, derivada da comparação de qualquer tipo de objeto
while
Loops
>> for i in 1..5>> puts i>> end12345=> 1..5# Experimente: 5.times { |i| puts i+1 }
Usado para repetir um bloco por um número conhecido de vezes.Pouco usado em Ruby, pois, para se iterar sobre coleções, usam-se os métodos aproriados, como, por exemplo, each.
for
Loops
>> for a in %w{a b c d}>> puts a >> endabcd=> ["a", "b", "c", "d"]
# Experimente: %w{a b c d}.each {|item| puts item}
for
Loops>> i = 5=> 5
>> until i==0>> puts i>> i -= 1>> end54321=> nil
O until é o contrário do while: ele repete o bloco de código até que a condição seja verdadeira
until
Loops
>> i = 0=> 0>> begin ?> puts i>> i += 1>> end while i < 00=> nil Utlizado em conjunto com o while ou until quando se deseja que
o bloco seja executado pelo menos uma vez
begin
Loops
>> loop do?> puts "a">> break if true>> enda=> nil
É o laço mais flexível. Ele será executado até que encontre um comando break ou return no bloco
loop
Padrões/ConvençõesMétodos que retornam booleanos costumam terminar com ?, para que pareçam perguntas aos objetos:
aluno.respond_to? :aprende
texto.empty?
Métodos que têm efeito colateral geralmente terminam com ! (bang)
conta.cancela!
Padrões/ConvençõesA comparação entre objetos é feita através do método == (sim, é um método!). A versão original apenas verifica se as referências apontam para os mesmos objetos. Pode-se reescrever este comportamento:
>> class Pessoa>> def ==(outra)>> self.cpf == outra.cpf>> end>> end=> nil
Padrões/ConvençõesNa definição de métodos, procure usar os parênteses. Para a chamada, prefira o que lhe for mais legível.
Nomes de variáveis, métodos e nomes de arquivos (terminados com .rb) em Ruby são sempre minúsculos e separados por “_”.
Variáveis com nomes maiúsculos são sempre constantes.
Para nomes de classes, utilize as regras de CamelCase
Padrões/Convenções
Módulos seguem o padrão de nomenclatura de classes
Métodos de leitura de uma variável de instância têm o mesmo nome da variável, sem o caracter @ no início, e métodos de escrita têm o mesmo nome terminado em =
Métodos que transformam um objeto em outro tem o nome iniciado por “to_”, p.ex., to_s, to_i, to_a, to_sym
Arquivos RubyTodos arquivos fonte contendo código Ruby devem ter a extensão .rb. Para carregar o código Ruby de outro arquivo, basta usar o método require:
O Ruby procura pelo arquivo em alguns diretórios pré-defindos (Ruby Load Path), incluindo o diretório atual. Caminhos relativos ou absolutos podem ser udados para incluir arquivos em outros diretórios:
require ‘meu_outro_fonte’
puts ObjetoDefinidoFora.new.algum_metodo
require ‘modulo/funcionalidades/coisa_importante’require ‘/usr/local/lib/my/libs/ultra_parser
Arquivos RubyA constante $:, ou $LOAD_PATH, contém diretórios do Load Path:
O comando require carrega o arquivo apenas uma vez. Para executar o conteúdo do arquivo diversas vezes, use
$:=> ["/Library/Ruby/Site/1.8", "/Library/Ruby/Site/1.8/powerpc-darwin9.0", ..., “.”]
load ‘meu_outro_arquivo.rb’load ‘meu_outro_arquivo.rb’# executado 2 vezes!
Referência
Urubatan, Rodrigo. “Ruby on Rails: desenvolvimento fácil e rápido de aplicação Web”. Novatec Editora. 2009.
Apostila do Curso de Ruby. Empresa Caelum. 2008.