Delegação com Forwardable
Parte da seção Programação orientada a objetos do Journey de Ruby da Coddy. Lição 46 de 57.
Delegação significa que um objeto transfere parte de seu trabalho para um objeto que ele contém, em vez de herdar dele. Uma playlist que contém um array de músicas é mais segura do que uma que é um array, porque o código externo só obtém os métodos que você escolhe encaminhar:
class Playlist
def initialize
@songs = []
end
def add(song)
@songs << song
self
end
def size
@songs.size
end
def first
@songs.first
end
end
list = Playlist.new.add("Intro").add("Dune")
puts list.size
puts list.firstSaída:
2
IntroEscrever cada método de encaminhamento manualmente é repetitivo. A biblioteca padrão Forwardable faz isso: extend Forwardable e, em seguida, def_delegators :@songs, :size, :first encaminha essas chamadas para o objeto em @songs:
require 'forwardable'
class Playlist
extend Forwardable
def_delegators :@songs, :size, :first, :last, :empty?, :include?
def initialize
@songs = []
end
def add(song)
@songs << song
self
end
end
list = Playlist.new.add("Intro").add("Dune")
puts "#{list.size} #{list.first} #{list.last}"
puts list.include?("Dune")
puts list.empty?Saída:
2 Intro Dune
true
falsedef_delegator :@songs, :push, :add encaminha um método com um novo nome. O objeto mantém controle total sobre tudo o que não encaminha, por exemplo delete ou clear:
require 'forwardable'
class Queue2
extend Forwardable
def_delegator :@jobs, :push, :enqueue
def_delegator :@jobs, :shift, :next_job
def_delegators :@jobs, :size
def initialize
@jobs = []
end
end
q = Queue2.new
q.enqueue("a")
q.enqueue("b")
puts q.next_job
puts q.size
puts q.respond_to?(:clear)Saída:
a
1
falsePrefira a delegação ("tem um") quando uma classe precisar apenas de parte do comportamento de outra classe. Herdar de Array exporia dezenas de métodos, como clear e delete_at, que poderiam violar as regras da playlist:
class Playlist < Array # todos os métodos de Array são públicos, incluindo clear
end
class Playlist # apenas o que você encaminha é público
extend Forwardable
def_delegators :@songs, :size, :each
endDesafio
FácilComplete a classe Playlist com Forwardable. Ela armazena músicas, cada uma um par [title, seconds], em @songs. Encaminhe size, empty? e first com def_delegators e encaminhe push com o nome add usando def_delegator. Seu próprio método duration retorna a duração total como m:ss, e titles retorna os títulos unidos por , .
O código fornecido adiciona uma música por linha de entrada (title,seconds) com add e depois imprime o tamanho, o primeiro título, os títulos, a duração e se a playlist responde a clear.
Seu código deve estar em playlist.rb. main.rb contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
require_relative 'playlist'
# Código de entrada/saída fornecido: mantenha-o como está
input = []
while (line = gets)
input << line.chomp
end
list = Playlist.new
input.each do |line|
title, seconds = line.split(",")
list.add([title, seconds.to_i])
end
puts "songs: #{list.size}"
puts "first: #{list.empty? ? "none" : list.first[0]}"
puts "titles: #{list.titles}"
puts "duration: #{list.duration}"
puts "can clear: #{list.respond_to?(:clear)}"
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação orientada a objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesVariáveis de InstânciaMétodos e selfto_s e inspectRevisão - Cartão da Biblioteca4Encapsulamento
Métodos privadosMétodos protegidosSetters privadosProtegendo o estadoRevisão - Máquina de venda automática7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMétodos Abstratoscase e ClassesRevisão - Métodos de Pagamento2Acessores e self
Leitores e GravadoresSetters Personalizadosself nos MétodosIdentidade e IgualdadeRecapitulação - Lista de Contatos5Herança
SubclassesSobrescrita de métodosChamando superis_a? e ancestraisRevisão - Folha de pagamento da equipe8Métodos Especiais
Igualdade e hashMétodos de OperadoresIndexação e AdiçãoColeções PersonalizadasRevisão - Frações11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de Ruby online