Menu
CoddyTech

Duck Typing

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

Ruby tidak memeriksa class suatu object sebelum memanggil method; object hanya perlu memiliki method tersebut. "Jika ia berjalan seperti bebek dan berkwek seperti bebek, berarti ia bebek." Inilah duck typing: class yang tidak memiliki superclass yang sama tetap dapat digunakan di tempat yang sama:

class Duck
  def speak
    "Quack"
  end
end

class Robot
  def speak
    "Beep"
  end
end

class Radio
  def speak
    "...news..."
  end
end

[Duck.new, Robot.new, Radio.new].each { |thing| puts thing.speak }

Output:

Quack
Beep
...news...

Class bawaan juga ikut berperan. Sebuah method yang hanya menggunakan << dapat bekerja dengan array, string, atau object apa pun milikmu yang mendefinisikan <<:

class Tally
  attr_reader :count

  def initialize
    @count = 0
  end

  def <<(_item)
    @count += 1
    self
  end
end

def export(items, target)
  items.each { |item| target << item.to_s }
  target
end

p export([1, 2], [])
p export([1, 2], +"")
puts export([1, 2, 3], Tally.new).count

Output:

["1", "2"]
"12"
3

respond_to?(:name) menanyakan apakah sebuah object memiliki method publik, tanpa memanggilnya. Gunakan ini saat sebuah object mungkin mendukung fitur opsional atau tidak:

class Printer
  def print_page(text)
    "printing #{text}"
  end
end

class Scanner
end

[Printer.new, Scanner.new].each do |device|
  if device.respond_to?(:print_page)
    puts device.print_page("report")
  else
    puts "#{device.class} cannot print"
  end
end

Output:

printing report
Scanner cannot print

Jika object tidak memiliki method tersebut, pemanggilan akan memunculkan NoMethodError, yang pesannya menyebutkan nama method dan object. Duck typing mengandalkan setiap object yang diteruskan untuk merespons method yang dikirimkan kepadanya:

def loudest(things)
  things.map(&:speak).max_by(&:size)
end

class Cat
  def speak
    "Meow"
  end
end

puts loudest([Cat.new, Cat.new])
begin
  loudest([Cat.new, 42])
rescue NoMethodError => e
  puts e.message
end

Keluaran:

Meow
undefined method `speak' for an instance of Integer
challenge icon

Tantangan

Mudah

Lengkapi class Printer dan LineCounter, serta fungsi pembantu export(items, target) di functions.rb. export mengirim setiap item ke target dengan target << item.to_s dan mengembalikan target. Printer#<< menampilkan teks dengan nomor baris, 1: text, lalu mengembalikan printer. LineCounter#<< menghitung baris dan karakter, lalu mengembalikan penghitung; to_s mengembalikan 3 lines, 12 chars.

Kode yang disediakan membaca item, lalu mengekspornya ke array (ditampilkan dengan p), ke string baru (ditampilkan dengan p), ke Printer, dan ke LineCounter (ditampilkan dengan puts).

Tempatkan kodemu di printer.rb, line_counter.rb, dan functions.rb. main.rb berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

require_relative 'printer'
require_relative 'line_counter'
require_relative 'functions'

# Kode input/output yang disediakan: biarkan apa adanya
input = []
while (line = gets)
  input << line.chomp
end
p export(input, [])
p export(input, +"")
export(input, Printer.new)
puts export(input, LineCounter.new)
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