38 - Objetos: métodos de clase

Para llamar a los métodos debemos definir un objeto de dicha clase. Hemos visto hasta ahora métodos de instancia que son los más comunes.

Hay situaciones donde podemos necesitar llamar a un método sin tener que definir un objeto de dicha clase. Este tipo de métodos son llamados métodos de clase.

Veremos un ejemplo para conocer su sintaxis en Ruby.

Problema 1:

Definir una clase Empleado que contenga un atributo de clase que almacena cuanto se le paga por hora a un empleado (12 dolares)

Al método initialize debe llegar el nombre y la cantidad de horas trabajadas.

Definir un método de clase que le enviemos un número de horas y nos retorne cuanto se le pagaría a un empleado con dicha cantidad de horas.

En el bloque principal mostrar cuanto se debería pagar a un empleado con 100 horas mensuales y otro con 125 horas.

Programa: ejercicio153.rb

class Empleado
  @@pago_hora = 12
  
  def initialize(nombre, horas_trabajo)
    @nombre = nombre
    @horas_trabajo = horas_trabajo
    @sueldo = horas_trabajo * @@pago_hora
  end

  def imprimir
    puts @nombre
    puts @horas_trabajo
    puts @sueldo
  end

  def self.pago_total(horas)
    horas * @@pago_hora
  end
end

# bloque principal

puts "Pago a un empleado por 100 horas : #{Empleado.pago_total(100)}"
puts "Pago a un empleado por 125 horas : #{Empleado.pago_total(125)}"

Lo primero que podemos ver es que en ningún momento en el bloque principal del programa definimos objetos de la clase Empleado.

Llamamos al método de clase directamente a partir del nombre de la clase:

Empleado.pago_total(100)

Para definir un método de clase en el lenguaje Ruby le antecedemos la palabra clave self al nombre del método:

  def self.pago_total horas
    horas * @@pago_hora
  end

En un método de clase solo podemos acceder a los atributos de clase y los parámetros.

No podemos acceder a los atributos @nombre, @horas_trabajadas y @sueldo. Tengamos en cuenta que no se han definidos objetos de la clase.

Tiene sentido que el método pago_total sea un método de clase. Pensemos que si por el momento no tenemos empleados y queremos saber cuanto nos costaría tener uno que trabaje 100 horas no tendría sentido tener que crear un objeto de la clase Empleado y llamar a un método que lo calcule.

Acotaciones

Hay otras dos sintaxis para definir métodos de clase que se obtiene idéntico resultado.

Segundo forma (antecedemos al nombre del método el nombre de la clase):

class Empleado
  @@pago_hora = 12
  
  def initialize(nombre, horas_trabajo)
    @nombre = nombre
    @horas_trabajo = horas_trabajo
    @sueldo = horas_trabajo * @@pago_hora
  end

  def imprimir
    puts @nombre
    puts @horas_trabajo
    puts @sueldo
  end

  def Empleado.pago_total horas
    horas * @@pago_hora
  end
end

puts "Pago a un empleado por 100 horas : #{Empleado.pago_total(100)}"
puts "Pago a un empleado por 125 horas : #{Empleado.pago_total(125)}"

Tercer forma (creando una clase interna con la sintaxis class << self) y dentro de la misma definiendo todos los métodos de clase:

class Empleado
  @@pago_hora = 12
  
  def initialize(nombre, horas_trabajo)
    @nombre = nombre
    @horas_trabajo = horas_trabajo
    @sueldo = horas_trabajo * @@pago_hora
  end

  def imprimir
    puts @nombre
    puts @horas_trabajo
    puts @sueldo
  end

  class << self
    def Empleado.pago_total horas
      horas * @@pago_hora
    end
  end  
  
end

puts "Pago a un empleado por 100 horas : #{Empleado.pago_total(100)}"
puts "Pago a un empleado por 125 horas : #{Empleado.pago_total(125)}"