Tipado pato
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 33 de 57.
Ruby no comprueba la clase de un objeto antes de llamar a un método; solo necesita que el objeto tenga el método. «Si camina como un pato y grazna como un pato, es un pato». Esto es la tipificación pato: las clases que no comparten ninguna superclase aún pueden usarse en el mismo lugar:
class Duck
def speak
"Quack"
end
end
class Robot
def speak
"Beep"
end
end
class Radio
def speak
"...news..."
end
end
[Duck.new, Robot.new, Radio.new].each { |thing| puts thing.speak }Salida:
Quack
Beep
...news...Las clases integradas también participan. Un método que solo usa << funciona con un array, una cadena o cualquier objeto tuyo que defina <<:
class Tally
attr_reader :count
def initialize
@count = 0
end
def <<(_item)
@count += 1
self
end
end
def export(items, target)
items.each { |item| target << item.to_s }
target
end
p export([1, 2], [])
p export([1, 2], +"")
puts export([1, 2, 3], Tally.new).countSalida:
["1", "2"]
"12"
3respond_to?(:name) pregunta si un objeto tiene un método público, sin llamarlo. Úsalo cuando un objeto pueda admitir o no una función opcional:
class Printer
def print_page(text)
"printing #{text}"
end
end
class Scanner
end
[Printer.new, Scanner.new].each do |device|
if device.respond_to?(:print_page)
puts device.print_page("report")
else
puts "#{device.class} cannot print"
end
endSalida:
printing report
Scanner cannot printCuando el objeto no tiene el método, la llamada genera NoMethodError, cuyo mensaje indica el nombre del método y el objeto. La tipificación pato se basa en que cada objeto que se pasa responda a los métodos que se le envían:
def loudest(things)
things.map(&:speak).max_by(&:size)
end
class Cat
def speak
"Meow"
end
end
puts loudest([Cat.new, Cat.new])
begin
loudest([Cat.new, 42])
rescue NoMethodError => e
puts e.message
endSalida:
Meow
undefined method `speak' for an instance of IntegerDesafío
FácilCompleta las clases Printer y LineCounter y el auxiliar export(items, target) en functions.rb. export envía cada elemento al destino con target << item.to_s y devuelve el destino. Printer#<< muestra el texto con un número de línea, 1: text, y devuelve la impresora. LineCounter#<< cuenta las líneas y los caracteres y devuelve el contador; su to_s devuelve 3 lines, 12 chars.
El código proporcionado lee los elementos, los exporta a un arreglo (mostrado con p), a una cadena nueva (mostrada con p), a un Printer y a un LineCounter (mostrado con puts).
Tu código debe ir en printer.rb, line_counter.rb y functions.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
require_relative 'printer'
require_relative 'line_counter'
require_relative 'functions'
# Código de entrada/salida suministrado: déjalo como está
input = []
while (line = gets)
input << line.chomp
end
p export(input, [])
p export(input, +"")
export(input, Printer.new)
puts export(input, LineCounter.new)
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