terça-feira, 3 de dezembro de 2013

Ruby 4 - Classes

Ruby 

 

Classes em Ruby

O código a seguir define uma classe chamada Person. Além de inicializar, o construtor usual cria novos objetos, ele tem dois métodos: 

  1. um para substituir o <=> operador de comparação (assim Array # sort pode classificar por idade)
  2. outro para substituir o método to_s (assim Kernel # puts pode formatar a sua saída).

Aqui, attr_reader é um exemplo de metaprogramação em Ruby: attr_accessor define métodos getter e setter de variáveis ​​de instância, mas attr_reader somente os métodos getter. 

A última declaração avaliada em um método é seu valor de retorno, permitindo a omissão de uma instrução de retorno explícita.

class Person
  attr_reader :name, :age
  def initialize(name, age)
    @name, @age = name, age
  end
  def <=>(person) # the comparison operator for sorting
    age <=> person.age
  end
  def to_s
    "#{name} (#{age})"
  end
end
 
group = [
  Person.new("Bob", 33),
  Person.new("Chris", 16),
  Person.new("Ash", 23)
]
 
puts group.sort.reverse
O código anterior exibe três nomes em ordem reversa de idade:
Bob (33)
Ash (23)
Chris (16)
 Person é uma constante e é uma referência a um objeto class.


Classes abertas


Em Ruby, as classes nunca estão fechadas: métodos podem sempre ser adicionados a uma classe existente. Isso se aplica a todas as classes, incluindo o padrão, classes internas.

Tudo que é necessário fazer é abrir uma definição de classe para uma classe existente e os novos conteúdos especificados serão adicionados aos conteúdos existentes.

Um exemplo simples de adicionar um novo método à classe Time da biblioteca padrão:

# re-open Ruby's Time class
class Time
  def yesterday
    self - 86400
  end
end
 
today = Time.now                            # => 2013-09-03 16:09:37 +0300
yesterday = today.yesterday                 # => 2013-09-02 16:09:37 +0300

Adicionando métodos a classes previamente definidas é freqüentemente chamado de monkey-patching (uma maneira de estender ou modificar o código em tempo de execução de linguagens dinâmicas, sem alterar o código fonte original). No entanto, se realizada de forma imprudente, essa prática pode levar a colisões de comportamento e resultados inesperados subsequentes e problemas com escalabilidade código.

Tratamento de Exceções


Uma exceção pode ser tratada com uma chamada raise:

raise
Uma mensagem opcional pode ser adicionada a exceção:
raise "This is a message"
Exceções pode também ser especificadas pelo programador:
raise ArgumentError, "Illegal arguments!"
Como alternativa, uma instância de exceção pode se passada ao método raise:
raise ArgumentError.new("Illegal arguments!")
Esta última estrutura é útil quando uma classe de exceção personalizada com um construtor que toma mais que um argumento precisa ser gerada:
class ParseError < Exception
  def initialize input, line, pos
    super "Could not parse '#{input}' at line #{line}, position #{pos}"
  end
end
 
raise ParseError.new("Foo", 3, 9)

Exceções poder ser tratadas com a cláusula rescue; esta cláusula pode captar exceções que herdam StandardError. Outra palavras chaves de controle de fluxo que pode ser usadas quando fizer tratamento de exceções são else e ensure : 
begin
  # do something
rescue
  # handle exception
else
  # do this if no exception was raised
ensure
  # do this whether or not an exception was raised
end
 É um erro comum tentar captar todas as exceções com uma simples cláusula rescue. Para captar todas as exceções, deve-se escrever:
begin
  # do something
rescue Exception
  # Exception handling code here.
  # Don't write only "rescue"; that only catches StandardError, a subclass of Exception.
end
Ou captar exceções particulares:
begin
  # do something
rescue RuntimeError
  # handle only RuntimeError and its subclasses
end
Também é possível especificar que o objeto exceção seja disponível para a cláusula de tratamento:
begin
  # do something
rescue RuntimeError => e
  # handling, possibly involving e, such as "puts e.to_s"
end
Alternativamente, a exceção mais recente é armazenada no genérico $. Muitas exceções pode ser também captadas:
begin
  # do something
rescue RuntimeError, Timeout::Error => e
  # handling, possibly involving e
end






Nenhum comentário:

Postar um comentário