Menu
Coddy logo textTech

Metody prywatne

Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 17 z 57.

Hermetyzacja oznacza, że obiekt ukrywa sposób swojego działania i udostępnia niewielki zestaw metod publicznych. Metody są domyślnie publiczne. Każda metoda zdefiniowana po słowie private w ciele klasy jest prywatna: własne metody obiektu mogą ją wywoływać, ale kod zewnętrzny nie może:

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

Wynik:

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

Wewnątrz klasy metoda prywatna jest wywoływana bez odbiorcy lub z użyciem self.. Próba wywołania jej na innym obiekcie, nawet tej samej klasy, jest odrzucana:

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

Wynik:

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

private może przyjmować również nazwę metody, a def zwraca nazwę metody, więc private def helper sprawia, że pojedyncza metoda staje się prywatna dokładnie w miejscu, w którym została zdefiniowana. Powyższe metody i metody znajdujące się wokół niej pozostają publiczne:

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)

Wynik:

Hello, Ada!
*waves*
[:salutation]

Metody pomocnicze trzymaj jako prywatne. Metody publiczne to obietnica, którą klasa składa pozostałej części programu; prywatne można później zmienić ich nazwy lub usunąć bez psucia żadnego kodu, który z nich korzysta:

class Invoice
  def total              # public: kod wywołujący na tym polega
    net + tax
  end

  private                # można później swobodnie zmienić

  def net
    ...
  end

  def tax
    ...
  end
end
challenge icon

Wyzwanie

Łatwy

Uzupełnij klasę Order. Jej jedyną publiczną metodą poza initialize jest receipt, która zwraca 3 x 12.50 = 37.50, tax 7.50, total 45.00. Prywatne metody subtotal (cena razy liczba sztuk), tax (20% wartości częściowej) i total obliczają te liczby.

Dostarczony kod odczytuje zamówienia z wierszy w formacie quantity price i drukuje każdy rachunek. Następnie próbuje wywołać tax z zewnątrz i drukuje tax is private, gdy Ruby odmawia.

Twój kod umieść w pliku order.rb. Plik main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

require_relative 'order'

# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Ruby online