Delegación con Forwardable
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 46 de 57.
La delegación significa que un objeto entrega parte de su trabajo a un objeto que contiene, en lugar de heredar de él. Una lista de reproducción que tiene un array de canciones es más segura que una que es un array, porque el código externo solo obtiene los métodos que eliges reenviar:
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.firstSalida:
2
IntroEscribir cada método de reenvío a mano es repetitivo. La biblioteca estándar Forwardable lo hace: extend Forwardable, después def_delegators :@songs, :size, :first reenvía esas llamadas al objeto en @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?Salida:
2 Intro Dune
true
falsedef_delegator :@songs, :push, :add reenvía un método con un nombre nuevo. El objeto mantiene el control total de todo lo que no reenvía, por ejemplo delete o 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)Salida:
a
1
falsePrefiere la delegación («tiene un») cuando una clase solo necesita parte del comportamiento de otra clase. Heredar de Array expondría docenas de métodos, como clear y delete_at, que podrían infringir las reglas de la lista de reproducción:
class Playlist < Array # todos los métodos de Array son públicos, incluyendo clear
end
class Playlist # solo lo que reenvías es público
extend Forwardable
def_delegators :@songs, :size, :each
endDesafío
FácilCompleta la clase Playlist con Forwardable. Contiene canciones, cada una un par [title, seconds], en @songs. Reenvía size, empty? y first con def_delegators, y reenvía push con el nombre add mediante def_delegator. Su propio método duration devuelve la duración total como m:ss, y titles devuelve los títulos unidos por , .
El código proporcionado añade una canción por cada línea de entrada (title,seconds) con add, después imprime el tamaño, el primer título, los títulos, la duración y si la lista de reproducción responde a clear.
Tu código va en playlist.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
require_relative 'playlist'
# Código de entrada/salida suministrado: déjalo tal 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 lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesVariables de instanciaMétodos y selfto_s e inspectRepaso: tarjeta de biblioteca4Encapsulación
Métodos privadosMétodos protegidosAsignadores privadosProtección del estadoRepaso: máquina expendedora7Polimorfismo y tipado pato
PolimorfismoTipado patoMétodos abstractoscase y clasesRepaso: métodos de pago2Accesores y self
Lectores y escritoresSetters personalizadosself en los métodosIdentidad e igualdadRepaso: lista de contactos5Herencia
SubclasesSobrescritura de métodosLlamar a superis_a? y ancestrosRepaso - Nómina del personal8Métodos especiales
Igualdad y hashMétodos de operadoresIndexación y adiciónColecciones personalizadasRepaso: fracciones11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de Ruby online