Menu
Coddy logo textTech

Forwardable ile Yetki Devri

Coddy'nin Ruby Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 46 / 57.

Delegasyon, bir nesnenin başka bir nesneden miras almak yerine işlerinin bir kısmını sahip olduğu bir nesneye devretmesi anlamına gelir. Şarkılardan oluşan bir diziye sahip olan çalma listesi, bir dizi olan çalma listesinden daha güvenlidir; çünkü dış kod yalnızca ileriye aktarmayı seçtiğiniz yöntemlere erişebilir:

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

Çıktı:

2
Intro

Her yönlendirme yöntemini elle yazmak tekrarlayıcıdır. Standart kütüphanedeki Forwardable bunu yapar: extend Forwardable, ardından def_delegators :@songs, :size, :first bu çağrıları @songs içindeki nesneye yönlendirir:

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?

Çıktı:

2 Intro Dune
true
false

def_delegator :@songs, :push, :add bir yöntemi yeni bir ad altında yönlendirir. Nesne, yönlendirmediği her şey üzerinde tam denetimi korur; örneğin delete veya 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)

Çıktı:

a
1
false

Bir sınıfın başka bir sınıfın davranışının yalnızca bir kısmına ihtiyaç duyduğu durumlarda delegasyonu ("has a") tercih edin. Array sınıfından kalıtım almak, çalma listesinin kurallarını bozabilecek clear ve delete_at gibi düzinelerce yöntemi açığa çıkarır:

class Playlist < Array      # her Array metodu public'tir, clear dahil
end

class Playlist              # yalnızca ilettiğiniz şeyler public'tir
  extend Forwardable
  def_delegators :@songs, :size, :each
end
challenge icon

Görev

Kolay

Playlist sınıfını Forwardable ile tamamla. Her biri [title, seconds] çifti olan şarkıları @songs içinde tutar. size, empty? ve first yöntemlerini def_delegators ile yönlendir; push yöntemini ise def_delegator ile add adı altında yönlendir. Kendi yöntemi olan duration, toplam uzunluğu m:ss biçiminde döndürür; titles ise başlıkları , ile birleştirerek döndürür.

Sağlanan kod, her girdi satırı (title,seconds) için add ile bir şarkı ekler, ardından boyutu, ilk başlığı, başlıkları, süreyi ve çalma listesinin clear yöntemine yanıt verip vermediğini yazdırır.

Kodun playlist.rb dosyasına yazılmalıdır. main.rb sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'playlist'

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Ruby derleyicisi