Menu
Coddy logo textTech

Duck Typing

Parte de la sección Programación Orientada a Objetos del Journey de Lua de Coddy. Lección 39 de 70.

A Lua no le importa la clase de un objeto. Solo le importa lo que el objeto puede hacer. Este concepto se llama tipado de pato: «Si camina como un pato y grazna como un pato, es un pato». En términos de programación, si un objeto tiene el método que estás llamando, funciona.

Esto significa que clases completamente no relacionadas pueden usarse juntas, siempre que compartan el mismo nombre de método:

local Circle = {}
Circle.__index = Circle
function Circle:new() 
    local obj = {}
    setmetatable(obj, Circle)
    return obj
end
function Circle:draw()
    print("Drawing a circle")
end

local Square = {}
Square.__index = Square
function Square:new()
    local obj = {}
    setmetatable(obj, Square)
    return obj
end
function Square:draw()
    print("Drawing a square")
end

Estas clases no tienen ninguna relación de herencia: son completamente independientes. Sin embargo, podemos tratarlas de forma idéntica:

local shapes = {Circle:new(), Square:new(), Circle:new()}

for _, shape in ipairs(shapes) do
    shape:draw()
end
-- Salida:
-- Dibujando un círculo
-- Dibujando un cuadrado
-- Dibujando un círculo

El bucle no comprueba de qué tipo es cada objeto. Simplemente llama a :draw() y confía en que el método exista. Esta flexibilidad es potente. Puedes añadir nuevos tipos de formas sin modificar el código del bucle en absoluto. Siempre que la nueva clase implemente :draw(), funciona sin más.

challenge icon

Desafío

Fácil

¡Demostremos el poder del tipado pato creando un sistema de notificaciones con clases completamente independientes que se puedan procesar de la misma manera!

Crearás tres clases de notificación independientes; ninguna hereda de las demás, pero todas implementan un método :send(). Esto significa que puedes recorrer una colección mixta y llamar a :send() en cada elemento sin preocuparte por su tipo real.

Organizarás tu código en cuatro archivos:

  • Email.lua: Una clase con un constructor :new(recipient) que almacena el destinatario del correo electrónico. Su método :send() debe imprimir Emailing {recipient}.
  • SMS.lua: Una clase completamente independiente con un constructor :new(phoneNumber). Su método :send() debe imprimir Texting {phoneNumber}.
  • PushNotification.lua: Otra clase independiente con un constructor :new(deviceId). Su método :send() debe imprimir Pushing to {deviceId}.
  • main.lua: ¡Une todo! Lee tres entradas, crea una instancia de cada tipo de notificación, colócalas todas en una sola tabla, después recórrela y llama a :send() en cada elemento.

Recibirás tres entradas:

  1. Un destinatario de correo electrónico (por ejemplo, alice@example.com)
  2. Un número de teléfono (por ejemplo, 555-1234)
  3. Un ID de dispositivo (por ejemplo, device_99)

En tu archivo principal, crea los tres objetos de notificación, almacénalos en una tabla e itera por la tabla llamando a :send() en cada uno. El orden debe ser: Email primero, después SMS y, por último, PushNotification.

Por ejemplo, si las entradas son bob@mail.com, 555-9876 y phone_42, la salida debería ser:

Emailing bob@mail.com
Texting 555-9876
Pushing to phone_42

Observa que tu bucle no necesita comprobar de qué tipo es cada objeto. Simplemente confía en que todos los objetos de la colección tienen un método :send(). ¡Eso es el tipado pato en acción! Si puede hacer :send(), es una notificación.

Pruébalo tú mismo

-- main.lua
-- Reúne todos los tipos de notificación y demuestra el duck typing

-- Importa las clases de notificación
local Email = require('Email')
local SMS = require('SMS')
local PushNotification = require('PushNotification')

-- Lee las entradas
local recipient = io.read()
local phoneNumber = io.read()
local deviceId = io.read()

-- TODO: Crea una instancia de cada tipo de notificación

-- TODO: Pon todas las notificaciones en una sola tabla (Email primero, luego SMS, luego PushNotification)

-- TODO: Recorre la tabla y llama a :send() en cada notificación
-- Esto demuestra el duck typing - no comprobamos el tipo, solo llamamos a :send()
quiz iconPonte a prueba

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

Practica por tu cuenta: Compilador de Lua online