Menu
CoddyTech

Forwardable ile Yetki Devri

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

Yetki devri, bir nesnenin başka bir nesneden kalıtım almak yerine, işlerinin bir kısmını sahip olduğu bir nesneye devretmesi anlamına gelir. Şarkılardan oluşan bir diziyi içeren çalma listesi, bir dizi olan çalma listesinden daha güvenlidir; çünkü dış kod yalnızca iletmeyi 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 tek bir yöntemi yeni bir ad altında iletir. Nesne, iletmediği her şey üzerinde tam kontrolü elinde tutar; ö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 başka bir sınıfın davranışının yalnızca bir kısmına ihtiyaç duyduğunda devretmeyi ("has a") tercih edin. Array sınıfından kalıtım almak, çalma listesinin kurallarını bozabilecek clear ve delete_at gibi onlarca yöntemi kullanıma açar:

class Playlist < Array      # clear dahil tüm Array metotları herkese açıktır
end

class Playlist              # yalnızca yönlendirdiğiniz metotlar herkese açıktır
  extend Forwardable
  def_delegators :@songs, :size, :each
end
challenge icon

Görev

Kolay

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

Verilen 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.

Kodunuzu playlist.rb dosyasına yazın. main.rb verilen girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'playlist'

# Sağlanan giriş/çıkış 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