Cap. 3 ­ Hierarquia de Classes

Anterior Índice Próximo

Hierarquia de Classes…

Nós terminamos a lição anterior criando duas novas classes: Coisa e Tesouro. Apesar destas duas classes compartilharem algumas características ( notadamente ambas têm um 'nome'), não existe conexão entre elas. Agora, estas duas classes são tão triviais que esta pequena repetição não faz tanta diferença. Entretanto, quando você começar a escrever programas reais com alguma complexidade, suas classes irão, freqüentemente, conter numerosas variáveis e métodos, e você não quer ficar recodificando aquele mesmo velho código de novo, outra vez e novamente…

Faz sentido, então, criar uma hierarquia de classes na qual uma classe que é um 'tipo especial' de alguma outra classe simplesmente 'herda' as características desta outra classe. No nosso simples jogo de estratégia, por exemplo, um Tesouro é um tipo especial de Coisa então a classe Tesouro deve herdar as características da classe Coisa.

Hierarquias de Classes - Ascendentes e Descendentes: Frequentemente é citado neste tutorial classes descendentes herdando caracter ísticas de suas classes ascendentes ( ou super classes, ou classes pai). Assim estes termos deliberadamente sugerem um tipo de relacionamento familiar entre as classes relacionadas. Em Ruby, cada classe possui somente um pai. Uma classe pode, entretanto, descender de uma longa e distinta árvore familiar com muitas gerações de avós, bisavós e assim por diante…

O comportamento de Coisas em geral serão codificados na classe Coisa A classe Tesouro irá automaticamente 'herdar' todas as características da classe Coisa, assim nós não temos que codificar tudo novamente.Ela precisará somente adicionar algumas características específicas de Tesouros.

Como regra geral, quando cria-se uma hierarquia de classes, a classe com o comportamento mais generalizado é a mais alta na hierarquia que as classes com comportamento mais específico. Assim a classe Coisa apenas com um nome (nome) e uma descrição (descricao), seria a superclasse da classe Tesouro que tem um nome, uma descrição e, adicionalmente, um valor. A classe Coisa também poderá ser uma superclasse de alguma outra classe específica como uma Arma que tem um nome, uma descrição e também alcance e assim por diante…

Um Pai, muitos Filhos

A figura acima ilustra a classe Coisa que tem um nome e uma descrição (em um programa Ruby, estas podem ser variáveis internas como @nome e @descricao mais alguns métodos para acessá-­las). As classes Tesouro e Arma descendem da classe Coisa então elas automaticamente herdam um nome e uma descricao. A classe Tesouro adiciona um novo item: valor - então ela agora tem nome, descrição e valor; A classe Arma adiciona alcance - assim ela tem nome, descricao e alcance.

Vamos ver como criar uma classe descendente em Ruby. Obeserve atentamente o código do programa estrategia.rb

estrategia.rb


<center>
<div style="border: 1px solid black; width: 100px">
estrategia.rb
</div>
</center>

# Como criar objetos descendentes

class Coisa
      def initialize( nome, descricao )
        @nome         = nome
        @descricao  = descricao
      end
      
      def get_nome
          return @nome
      end
      
      def set_nome( nome )
          @nome = nome
      end
      
      def get_descricao
          return @descricao
      end
      
      def set_descricao( descricao )
          @descricao = descricao
      end
end      
    
    
class Tesouro < Coisa #Tesouro descende de Coisa
      def initialize( nome, descricao, valor )
          super( nome, descricao )
          @valor = valor
      end
      
      def get_valor
          return @valor
      end
      
      def set_valor( valor )
          @valor = valor
      end
end
    
# Início do programa
  t1 = Tesouro.new("Espada de Arwen", "uma arma élfica.", 800)
  t2 = Treasure.new("Anduril", "espada de rei Aragorn", 550) 
  puts "Este é tesouro1: #{t1.inspect}"
  puts "Este é um tesouro2: #{t2.inspect}"
  puts "t1 nome=#{t1.get_nome}, descrição=#{t1.get_descricao}, valor=#{t1.get_valor}"
  t1.set_valor( 100 )
  t1.set_nome( 'Fighting Knives' )
  t1.set_descricao("facas voadoras de Legolas")
  puts "t1 (Agora) nome=#{t1.get_nome}, descricao=#{t1.get_descricao}, valor=#{t1.get_valor}"

Este começa com uma definição da classe Coisa que tem duas variáveis de instância, @nome e @descricao. A estas variáveis são atribuidos valores no método initialize quando um novo objeto Coisa é criado.

Variáveis de instância geralmente não podem ( e não devem ) ser acessadas diretamente pelo mundo exterior da classe devido ao princípio do encapsulamento.

Encapsulamento é um termo que se refere à modularidade de um objeto. De forma simples, significa que somente o próprio objeto pode mexer com o seu estado interno. O mundo externo não. O benefício disso é que o programador poderá mudar a implementação dos métodos sem ter que se preocupar com algum código externo que dependa de algum detalhe específico da implementação anterior.

Para obter o valor de cada variável em um objeto Coisa nós precisamos de um método get como get_nome para passar um novo valor para uma variável nós precisamos de um método set como set_nome:

def get_nome
       return @nome
end

def set_nome( nome )
       @nome = nome
end

Superclasses e Subclasses

Agora olhe a classe Tesouro. Veja como é declarada:
class Tesouro < Coisa

O sinal de menor , < , indica que Tesouro é uma subclasse, ou descendente, de Coisa e por isso ela herda os dados (variáveis) e o comportamento (métodos) da classe Coisa. Como os métodos get_nome, set_nome, get_descricao e set_descricao já existem na classe ascendente(Coisa) estes métodos não precisam ser recodificados na classe descendente (Tesouro).

A classe Tesouro tem uma peça adicional de dado, seu valor (@valor) e foram escritos acessores get e set para ele. Quando um novo objeto Tesouro é criado, seu método initialize é automaticamente chamado. Um objeto Tesouro tem três variáveis para inicializar (@nome, @descricao e @valor), então seu método initialize recebe três argumentos:

def initialize( nome, descricao, valor )

Os primeiros dois argumentos são passados, usando a palavra­-chave super, para o método initialize da superclasse (Coisa) assim o método initialize da classe Coisa pode lidar com elas:

super( nome, descricao )

Quando usado dentro de um método, a palavra-­chave super chama o método com o mesmo nome na classe ascendente ou superclasse.

O método atual da classe Tesouro é chamado initialize assim quando o código interno passa os dois argumentos ( nome, descricao ) para super realmente está passando­ para o método initialize da sua superclasse, Coisa. Se a palavra-­chave super for usada, sem qualquer argumento, todos os argumentos enviados ao método atual são passados para o método ascendente.

Anterior Índice Próximo

-- LeandroNunes - 18 Oct 2006
Topic revision: r1 - 05 Jul 2008, UnknownUser
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-Colivre? Send feedback