Menu
CoddyTech

Delegasi dengan Forwardable

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Ruby di Coddy. Pelajaran 46 dari 57.

Delegasi berarti sebuah object menyerahkan sebagian pekerjaannya kepada object yang dimilikinya, alih-alih mewarisi darinya. Playlist yang memiliki array berisi lagu lebih aman daripada playlist yang merupakan array, karena kode dari luar hanya mendapatkan method yang kamu pilih untuk diteruskan:

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

Output:

2
Intro

Menulis setiap method penerusan secara manual itu berulang-ulang. Library standar Forwardable melakukannya: extend Forwardable, lalu def_delegators :@songs, :size, :first meneruskan pemanggilan tersebut ke object di @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?

Output:

2 Intro Dune
true
false

def_delegator :@songs, :push, :add meneruskan satu method dengan nama baru. object tetap memegang kendali penuh atas semua hal yang tidak diteruskannya, misalnya delete atau 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)

Output:

a
1
false

Utamakan delegasi ("memiliki") ketika sebuah class hanya memerlukan sebagian perilaku dari class lain. Mewarisi dari Array akan mengekspos puluhan method, seperti clear dan delete_at, yang dapat melanggar aturan playlist:

class Playlist < Array      # semua method Array bersifat publik, termasuk clear
end

class Playlist              # hanya yang kamu teruskan bersifat publik
  extend Forwardable
  def_delegators :@songs, :size, :each
end
challenge icon

Tantangan

Mudah

Lengkapi class Playlist dengan Forwardable. Class ini menyimpan lagu, masing-masing berupa pasangan [title, seconds], di @songs. Teruskan size, empty?, dan first dengan def_delegators, lalu teruskan push dengan nama add menggunakan def_delegator. Method-nya sendiri, duration, mengembalikan durasi total dalam format m:ss, sedangkan titles mengembalikan judul-judul yang digabungkan dengan , .

Kode yang disediakan menambahkan satu lagu untuk setiap baris input (title,seconds) menggunakan add, lalu mencetak jumlah lagu, judul lagu pertama, semua judul, durasi, dan apakah playlist merespons clear.

Tulis kodemu di playlist.rb. main.rb berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

require_relative 'playlist'

# Kode input/output yang disediakan: biarkan apa adanya
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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Ruby online