Skip to content

Instantly share code, notes, and snippets.

@germanescobar
Last active October 18, 2018 21:07
Show Gist options
  • Save germanescobar/feceec0abca41f047676e79bd30a1aef to your computer and use it in GitHub Desktop.
Save germanescobar/feceec0abca41f047676e79bd30a1aef to your computer and use it in GitHub Desktop.

Para hacer algunos ejemplos de herencia, métodos y atributos de clase vamos a modelar un sistema de nómina para una compañía.

Empezamos con una clase Employee de la cual van a extender otras clases:

class Employee
  attr_reader :name, :email, :salary
  
  def initialize(attrs)
    @name = attrs[:name]
    @email = attrs[:email]
    @password = attrs[:password]
    @salary = attrs[:salary]
  end
  
  def validate_password
    password.length >= 5 && password.length <= 40
  end
end

Acá es importante mencionar que podríamos haber recibido múltiples argumentos en el initialize, pero cuando son más de dos argumentos es mejor utilizar un hash:

e1 = Employee.new(name: "Pedro", email: "pedro@gmail.com", password: "test1234", salary: 200)

Hay dos tipos de empleados: Manager y Worker. Los dos extienden de Employee. El ejercicio es primero definirlos:

class Manager < Employee
  def initialize(attrs={})
    super(attrs) # también es posible copiar lo del padre pero es mejor así
  end
end

class Worker < Employee
  def initialize(attrs={})
    super(attrs)
  end
end

Un ejercicio adicional es instanciar un Manager y un Worker y mostrar la clase de cada uno (se les dice que con el método class pueden obtener la clase):

m1 = Manager.new
puts m1.class # Manager

w1 = Worker.new
puts w1.class # Worker

Los Wokers tienen un atributo adicional hours que inicia en 0 y que representa el número de horas que han trabajado y un método work que reciba un parámetro con el número de horas que se deben sumar:

class Worker < Employee
  attr_reader :hours
  
  def initialize(attrs)
    super(attrs)
    @hours = 0
  end
  
  def work(hours)
    @hours += hours
  end
end

Los Managers tienen unos Workers a su cargo y deben tener un método report que devuelve el número de horas totales trabajadas por sus Workers:

class Manager < Employee
  attr_reader :workers
  
  def initialize(attrs)
    super(attrs)
    @workers = attrs[:workers]
  end
  
  def report
    total = 0
    @workers.each do |worker|
      total += worker.hours
    end
    total
  end
end

Driver code, esto se les puede mostrar para que vean cómo se va a utilizar:

pedro = Worker.new(name: "Pedro", email: "pedro@gmail.com", password: "test1234", salary: 200)
juan = Worker.new(name: "Juan", email: "juan@gmail.com", password: "test1234", salary: 200)

joshua = Manager.new(name: "Joshua", email: "joshua@gmail.com", password: "test1234", salary: 1000, workers: [pedro, juan])

pedro.work(10)
juan.work(20)
pedro.work(10)

puts "Los trabajadores de Joshua trabajaron #{joshua.report} horas"

Polimorfismo

El siguiente ejercicio es modificar Employee para cargar una lista de employees:

def Employee
  def self.find_all
    pedro = Worker.new(name: "Pedro", email: "pedro@gmail.com", password: "test1234", salary: 200)
    juan = Worker.new(name: "Juan", email: "juan@gmail.com", password: "test1234", salary: 200)

    joshua = Manager.new(name: "Joshua", email: "joshua@gmail.com", password: "test1234", salary: 1000, workers: [pedro, juan])
    
    [pedro, juan, joshua]
  end
end

employees = Employee.find_all
employees.each do |e|
  text = "El empleado #{e.name} es un #{e.class}"
  if e.is_a? Manager
    text += " y su grupo ha trabajado #{e.report} horas"
  elsif e.is_a? Worker
    text += " y ha trabajado #{e.hours} horas"
  end
end

Sobrescribiendo métodos

class Triangle
def draw
"""
/\\
/ \\
/____\\
"""
end
end
class Circle
def draw
"""
= =
= =
= =
= =
= =
"""
end
end
class Square
def draw
"""
_ _ _ _
| |
| |
|_ _ _ _|
"""
end
end
shapes = [
Triangle.new,
Circle.new,
Square.new,
Circle.new,
Triangle.new
]
shapes.each do |shape|
puts shape.draw
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment