Menu
Coddy logo textTech

보호된 메서드

Coddy Ruby 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 18번째.

protected 메서드는 public과 private의 중간에 해당합니다. 코드 외부에서는 이 메서드를 호출할 수 없지만, 같은 클래스의 모든 객체는 다른 객체에서 이 메서드를 호출할 수 있습니다. 이를 통해 두 객체는 프로그램의 나머지 부분에 표시하지 않는 데이터를 서로 비교할 수 있습니다:

class Account
  def initialize(owner, balance)
    @owner = owner
    @balance = balance
  end

  def richer_than?(other)
    balance > other.balance
  end

  protected

  def balance
    @balance
  end
end

ada = Account.new("Ada", 500)
bo = Account.new("Bo", 300)
puts ada.richer_than?(bo)
begin
  ada.balance
rescue NoMethodError => e
  puts e.message
end

출력:

true
protected method `balance' called for an instance of Account

private와의 차이는 수신자가 다른 객체일 때 드러납니다. other.balance는 protected 메서드에서는 작동하지만 private 메서드에서는 실패합니다:

class Sample
  def initialize(n)
    @n = n
  end

  def compare_protected(other)
    other.guarded + guarded
  end

  def compare_private(other)
    other.hidden + hidden
  rescue NoMethodError
    "private refused other.hidden"
  end

  protected

  def guarded
    @n
  end

  private

  def hidden
    @n
  end
end

a = Sample.new(1)
b = Sample.new(2)
puts a.compare_protected(b)
puts a.compare_private(b)

출력:

3
private refused other.hidden

protected는 attr_reader와도 함께 사용할 수 있습니다. 이는 일반적으로 한 클래스의 객체들 사이에서만 값을 공유하는 방법이며, 예를 들어 두 객체 중 어느 것이 이기는지 결정할 때 사용할 수 있습니다.

class Player
  attr_reader :name

  def initialize(name, rating)
    @name = name
    @rating = rating
  end

  def stronger?(other)
    rating > other.rating
  end

  protected

  attr_reader :rating
end

a = Player.new("Ada", 1200)
b = Player.new("Bo", 1100)
puts a.stronger?(b)
puts [a, b].select { |pl| pl.stronger?(b) }.map(&:name).inspect

출력:

true
["Ada"]

작동하는 가장 좁은 수준을 선택하세요. public은 클래스의 인터페이스에, protected는 클래스의 객체들이 서로 비교하는 데이터에, private은 그 외의 모든 것에 사용합니다:

public      # 누구나: order.total
protected   # 클래스의 객체들: Account 내부의 other.balance
private     # 객체 자신만: subtotal, self.subtotal
challenge icon

챌린지

쉬움

Account 클래스를 완성하세요. 잔액은 다른 계정만 읽을 수 있어야 하므로, 해당 리더를 protected로 만드세요. richer_than?(other)는 잔액을 비교하고, transfer_to(other, amount)는 다른 계정의 protected 메서드인 receive(amount)를 통해 다른 계정으로 돈을 이동한 후 true를 반환합니다. 잔액이 부족하면 false를 반환합니다. to_s는 소유자의 이름만 반환합니다.

제공된 코드는 두 소유자와 잔액을 읽은 다음 transfer a b 50 명령을 처리하며, ok 또는 refused를 출력합니다. 그런 다음 Ada is richer(또는 Bo is richer, 또는 equal)를 출력하고, 마지막으로 외부에서 balance를 읽으려고 시도하여 Ruby가 거부하면 balance is protected를 출력합니다.

코드는 account.rb에 작성하세요. main.rb에는 제공된 입력/출력 코드가 들어 있으며 수정할 수 없습니다.

직접 해보기

require_relative 'account'

# 제공된 입력/출력 코드: 그대로 유지하세요
input = []
while (line = gets)
  input << line.chomp
end
accounts = input[0..1].map do |line|
  owner, balance = line.split
  Account.new(owner, balance.to_i)
end
a, b = accounts
input.drop(2).each do |line|
  _, from, to, amount = line.split
  source = from == "a" ? a : b
  target = to == "a" ? a : b
  puts source.transfer_to(target, amount.to_i) ? "ok" : "refused"
end
if a.richer_than?(b) then puts "#{a} is richer"
elsif b.richer_than?(a) then puts "#{b} is richer"
else puts "equal"
end
begin
  a.balance
  puts "balance is public"
rescue NoMethodError
  puts "balance is protected"
end
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Ruby 컴파일러