Menu
Coddy logo textTech

Métodos privados

Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 17 de 57.

La encapsulación significa que un objeto oculta cómo funciona y ofrece un pequeño conjunto de métodos públicos. Los métodos son públicos de forma predeterminada. Todo método definido después de la palabra private en el cuerpo de una clase es privado: los propios métodos del objeto pueden llamarlo, pero el código externo no:

class Order
  def initialize(price, quantity)
    @price = price
    @quantity = quantity
  end

  def total
    subtotal + shipping
  end

  private

  def subtotal
    @price * @quantity
  end

  def shipping
    subtotal >= 50 ? 0 : 5
  end
end

order = Order.new(10, 3)
puts order.total
begin
  order.subtotal
rescue NoMethodError => e
  puts e.message
end

Salida:

35
private method `subtotal' called for an instance of Order

Dentro de la clase, se llama a un método privado sin un receptor o con self.. Se rechaza llamarlo en otro objeto, incluso si es de la misma clase:

class Coin
  def initialize(cents)
    @cents = cents
  end

  def describe
    "#{self.label} / #{label}"
  end

  def same_as?(other)
    other.label == label
  end

  private

  def label
    "#{@cents}c"
  end
end

a = Coin.new(5)
puts a.describe
begin
  a.same_as?(Coin.new(5))
rescue NoMethodError => e
  puts e.message
end

Salida:

5c / 5c
private method `label' called for an instance of Coin

private también puede recibir un nombre de método, y def devuelve el nombre del método, por lo que private def helper hace que un solo método sea privado justo donde se define. Los métodos que están arriba y alrededor siguen siendo públicos:

class Greeter
  def greet(name)
    "#{salutation}, #{name}!"
  end

  private def salutation
    "Hello"
  end

  def wave
    "*waves*"
  end
end

g = Greeter.new
puts g.greet("Ada")
puts g.wave
p Greeter.private_instance_methods(false)

Salida:

Hello, Ada!
*waves*
[:salutation]

Mantén privados los helpers. Los métodos públicos son la promesa que una clase hace al resto del programa; los privados se pueden renombrar o eliminar más adelante sin romper a ningún código que los invoque:

class Invoice
  def total              # público: los llamadores confían en él
    net + tax
  end

  private                # libre de cambiar más tarde

  def net
    ...
  end

  def tax
    ...
  end
end
challenge icon

Desafío

Fácil

Completa la clase Order. Su único método público además de initialize es receipt, que devuelve 3 x 12.50 = 37.50, tax 7.50, total 45.00. Los métodos privados subtotal (precio por cantidad), tax (el 20 % del subtotal) y total calculan los números.

El código proporcionado lee los pedidos como líneas con el formato quantity price e imprime cada recibo. Después intenta llamar a tax desde fuera e imprime tax is private cuando Ruby lo rechaza.

Tu código va en order.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

require_relative 'order'

# Código de entrada/salida suministrado: déjalo tal como está
input = []
while (line = gets)
  input << line.chomp
end
orders = input.map do |line|
  quantity, price = line.split
  Order.new(quantity.to_i, price.to_f)
end
orders.each { |o| puts o.receipt }
begin
  orders[0].tax
  puts "tax is public"
rescue NoMethodError
  puts "tax is private"
end
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 Ruby online