الكتابة بأسلوب البطة
جزء من قسم البرمجة كائنية التوجه في رحلة Ruby على Coddy. الدرس 33 من 57.
لا تتحقق Ruby من فئة الكائن قبل استدعاء طريقة؛ فهي تحتاج فقط إلى أن يمتلك الكائن الطريقة. «إذا كان يمشي مثل البطة ويصيح مثل البطة، فهو بطة». يُسمّى هذا الكتابة بأسلوب البطة: إذ يمكن استخدام الفئات التي لا تشترك في أي فئة فائقة في المكان نفسه:
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 }الناتج:
Quack
Beep
...news...تشارك الفئات المضمّنة أيضًا. تعمل الطريقة التي تستخدم << فقط مع مصفوفة أو سلسلة نصية أو أي كائن خاص بك يعرّف <<:
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الناتج:
["1", "2"]
"12"
3يسأل respond_to?(:name) عما إذا كان الكائن يمتلك طريقة عامة، من دون استدعائها. استخدمه عندما قد يدعم الكائن ميزة اختيارية أو لا يدعمها:
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الناتج:
printing report
Scanner cannot printعندما لا يمتلك الكائن الطريقة، يرفع الاستدعاء NoMethodError، التي تسمي الطريقة والكائن في رسالتها. تعتمد الكتابة بأسلوب البطة على أن يجيب كل كائن يتم تمريره عن الطرق المرسلة إليه:
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الناتج:
Meow
undefined method `speak' for an instance of Integerالتحدي
سهلأكمل الصنفين Printer وLineCounter والمساعد export(items, target) في functions.rb. ترسل export كل عنصر إلى الهدف باستخدام target << item.to_s وتُرجع الهدف. تطبع Printer#<< النص مع رقم السطر، 1: text، وتُرجع الطابعة. يحسب LineCounter#<< الأسطر والأحرف ويُرجع العداد؛ وتُرجع to_s الخاصة به 3 lines, 12 chars.
يقرأ الكود المُزوَّد العناصر، ويصدّرها إلى مصفوفة (تُطبع باستخدام p)، وإلى سلسلة نصية جديدة (تُطبع باستخدام p)، وإلى Printer وإلى LineCounter (تُطبع باستخدام puts).
يجب أن تضع كودك في printer.rb وline_counter.rb وfunctions.rb. يحتوي main.rb على كود الإدخال/الإخراج المُزوَّد ولا يمكن تعديله.
جرّب بنفسك
require_relative 'printer'
require_relative 'line_counter'
require_relative 'functions'
# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input = []
while (line = gets)
input << line.chomp
end
p export(input, [])
p export(input, +"")
export(input, Printer.new)
puts export(input, LineCounter.new)
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت