:: Topo :: doCoding :: Linguagens de Programação :: Ruby :: FORPC101 ::

Week-10

Aprendizagem

Serialização

Diversas linguagens de programação têm a capacidade de “serializar” objectos, que permite o armazenamento - persistência - de um objecto fora do programa e a sua posterior reconstituição. Em Ruby esta funcionalidade designa-se por marshaling. A classe Marshal define dois métodos:

  1. dump() - para armazenar o objecto em ficheiro para posterior reconstituição.
  2. load() - para reconstituir um objecto a partir do ficheiro de dump.
A classe Marshal apenas “serializa” estruturas de dados. Não consegue serializar código Ruby - por exemplo em objectos Proc - ou recursos alocados por outros processos - tais como file handlers ou database connections. Nestes casos a classe Marshal retorna um erro.

Constantes

  1. As constantes em Ruby são como as variáveis, excepto que por convenção começam com uma letra maiúscula e porque os seus valores são supostos manterem-se constantes durante toda a execução do programa.
  2. As constantes definidas em classes são acessíveis com ClassName::CONSTANT_NAME. As constantes do mesmo scope são acessíveis directamente as-is ou prefixadas com ::CONSTANT_NAME.
O interpretador não realidade não força a constâncias das constantes, mas devolve um aviso caso o programa tente alterar o valor de uma constante.

Módulos

  1. Os módulos são semelhantes às classes: ambos definem um conjunto de métodos, constantes e contêm definições de outros módulos ou classes.
  2. Os módulos são diferentes das classes:
    • a definição é feita por module, em vez de ser por class.
    • não é permitido instanciar objectos a partir de módulos.
    • não é permitido derivar módulos de outros módulos.
    • não existe hierarquia ou herança em módulos.
  3. Os módulos são “acrescentados” às classes ou aos objectos para estenderem as funcionalidades destes com as funcionalidades definidas nos módulos.
  4. Os módulos cumprem 2 propósitos:
    • Actuam como namespaces, permitindo a definição de métodos cujos identificadores - nomes - nunca entram em conflito com outros definidos fora do seu módulo.
    • Permitem partilhar funcionalidades entre classes: se uma classe incluir - mixin - um módulo então os métodos deste ficam disponíveis tal como se fossem métodos da própria classe. São “misturados” - mixed in. Para isso existe o método include(), que tal como os métodos load() e require() carregam código Ruby a partir de ficheiros.
  5. Os nomes para classes, por convenção, são pronomes. Os nomes para módulos, também por convenção, são normalmente adjectivos. Por exemplo: class Stack ou módulo Stacklike.
Apesar de cada classe ser um módulo, o método include() não permite que uma classe inclua outra classe.
A principal diferença entre herdar de uma classe ou misturar um módulo é que é possível misturar mais do que um módulo. Uma classe apenas pode herdar de uma e de uma só classe. Caso se pretenda que as instâncias de uma classe tenham comportamentos extra - e não é desejável acumular esses comportamentos na classe mãe - pode-se organizar o código de forma mais modular com recurso aos módulos. Cada módulo pode adicionar algo diferente aos métodos da classe.

Self

  1. a cada ponto de execução de um programa Ruby existe um e um só self. O self é o objecto default ou actualmente acessível ao programa num dado ponto do código. Existe um pequeno conjunto de regras para determinar o self:
    • Top level context
      O contexto de nível topo é o contexto antes de entrar em qualquer outro contexto, tal como a definição de uma classe. Portanto, esta regra define o self como sendo o código escrito fora de qualquer classe ou módulo - designa-se por main.
    • Self inside class and module definitions
      No contexto definido por uma classe ou módulo, o self é o objecto dessa classe ou módulo.
    • Self in instance method definitions
      No contexto definido por um método, o self será o futuro objecto que aceder a este método.
    • Self in singleton-method and class-method definitions
      Um método singleton é um método associado a um objecto e que só pode ser evocado por um e um só objecto. Neste contexto, o self é o objecto que define esse método. Os métodos de classe são métodos singleton para objectos dessa classe.

Exercícios

Exercício 1

exercise-01-klass.rb

=begin
Write a Ruby program named lesson10exercise1.rb
that defines a class called Klass and
which will be called in another program as follows:
 
o = Klass.new("hello")
puts o.sayHello
 
where sayHello is a method in that class,
which returns the string sent when an object of Klass is created.
 
Write another program named lesson10exercise1a.rb
that creates an object of the class defined in program lesson10exercise1.rb and
then marshals it and then restores it.
=end
 
class Klass
 
  def initialize string
    @string    = string
    @timestamp = Time.now
  end
 
  def sayHello
    @string
  end
 
  def getTimestamp
    @timestamp
  end
 
end

exercise-01-dump.rb

require 'exercise-01-klass'
 
o = Klass.new("hello")
puts o.sayHello
puts o.getTimestamp
 
File.open('klass.dump', 'w+') do | file_handler |
  Marshal.dump o, file_handler
end

exercise-01-load.rb

require 'exercise-01-klass'
 
o = nil
File.open('klass.dump', 'r') do | file_handler |
  o = Marshal.load file_handler
end
 
puts o.sayHello
puts o.getTimestamp

Exercício 2

exercise-02-fix.rb

=begin
You are using a class (say DTRConvertor)
that’s got a bug in one of its methods
(the bug is that the conversion rate is Rs 38).
 
You know where the bug is and how to fix it,
but you can’t or don’t want to change the source file itself.
Write code to do it.
 
The original class is:
 
class DTRConvertor
  def convert(dollar_amount)
    return dollar_amount * 40.0 # Bug here
  end
end
 
m = DTRConvertor.new
puts m.convert(100.0)
=end
 
require 'exercise-02'
 
# Fix by Sub-Classing it:
class DTRConvertorFixed < DTRConvertor
 
  def convert(dollars = 1.0)
    dollars * 38.0
  end
 
end
 
# Fix with aliasing of buggy method:
class DTRConvertor
 
  alias old_convert convert
 
  def convert(dollars = 1.0)
    dollars * 38.0
  end
 
end

Questionário

Referências

Considerações

Pontos Altos

Esta secção regista o que considero serem os pontos altos da linguagem Ruby quando comparada com outras linguagens que conheço.

  1. Marshaling não podia ser mais simples.
  2. Mixins permitem algo semelhante a múltipla herança, talvez sem a complicação de outras linguagens.

Pontos Baixos

Esta secção regista o que considero serem os pontos baixos da linguagem Ruby quando comparada com outras linguagens que conheço.

 
docoding/languages/ruby/forpc101/week-10.txt · Modificado em: 2008/09/25 10:07 por straider     Voltar ao topo