Menu
Coddy logo textTech

Forwardable을 활용한 위임

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

위임은 객체가 다른 객체로부터 상속하는 대신, 자신이 보유한 객체에 작업의 일부를 넘기는 것을 의미합니다. 노래 배열인 플레이리스트보다 노래 배열을 포함하는 플레이리스트가 더 안전합니다. 외부 코드가 호출할 수 있는 것은 여러분이 전달하기로 선택한 메서드뿐이기 때문입니다:

class Playlist
  def initialize
    @songs = []
  end

  def add(song)
    @songs << song
    self
  end

  def size
    @songs.size
  end

  def first
    @songs.first
  end
end

list = Playlist.new.add("Intro").add("Dune")
puts list.size
puts list.first

출력:

2
Intro

각 전달 메서드를 직접 작성하는 것은 반복적인 작업입니다. 표준 라이브러리의 Forwardable이 이를 처리합니다. extend Forwardable을 사용한 다음, def_delegators :@songs, :size, :first는 해당 호출을 @songs의 객체로 전달합니다:

require 'forwardable'

class Playlist
  extend Forwardable
  def_delegators :@songs, :size, :first, :last, :empty?, :include?

  def initialize
    @songs = []
  end

  def add(song)
    @songs << song
    self
  end
end

list = Playlist.new.add("Intro").add("Dune")
puts "#{list.size} #{list.first} #{list.last}"
puts list.include?("Dune")
puts list.empty?

출력:

2 Intro Dune
true
false

def_delegator :@songs, :push, :add는 하나의 메서드를 새 이름으로 전달합니다. 객체는 전달하지 않는 모든 작업, 예를 들어 delete 또는 clear를 완전히 제어합니다:

require 'forwardable'

class Queue2
  extend Forwardable
  def_delegator :@jobs, :push, :enqueue
  def_delegator :@jobs, :shift, :next_job
  def_delegators :@jobs, :size

  def initialize
    @jobs = []
  end
end

q = Queue2.new
q.enqueue("a")
q.enqueue("b")
puts q.next_job
puts q.size
puts q.respond_to?(:clear)

출력:

a
1
false

클래스에 다른 클래스 동작의 일부만 필요한 경우에는 상속("has a")보다 위임을 선호하세요. Array를 상속하면 clear와 delete_at 같은 수십 개의 메서드가 노출되어 플레이리스트의 규칙을 깨뜨릴 수 있습니다:

class Playlist < Array      # 모든 Array 메서드가 public이며, clear도 포함됩니다
end

class Playlist              # 전달한 것만 public입니다
  extend Forwardable
  def_delegators :@songs, :size, :each
end
challenge icon

챌린지

쉬움

Forwardable을 사용하여 Playlist 클래스를 완성하세요. 이 클래스는 각각 [title, seconds] 쌍인 곡들을 @songs에 저장합니다. def_delegators를 사용하여 size, empty? 및 first를 전달하고, def_delegator를 사용하여 push를 add라는 이름으로 전달하세요. 자체 메서드인 duration은 전체 길이를 m:ss 형식으로 반환하고, titles는 제목들을 , 로 연결하여 반환합니다.

제공된 코드는 입력 줄마다 하나의 곡(title,seconds)을 add로 추가한 다음, 곡의 수, 첫 번째 제목, 제목 목록, 재생 시간 및 재생 목록이 clear에 응답하는지를 출력합니다.

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

직접 해보기

require_relative 'playlist'

# 제공된 입력/출력 코드: 그대로 유지하세요
input = []
while (line = gets)
  input << line.chomp
end
list = Playlist.new
input.each do |line|
  title, seconds = line.split(",")
  list.add([title, seconds.to_i])
end
puts "songs: #{list.size}"
puts "first: #{list.empty? ? "none" : list.first[0]}"
puts "titles: #{list.titles}"
puts "duration: #{list.duration}"
puts "can clear: #{list.respond_to?(:clear)}"
quiz icon실력 점검

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

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

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