الكتابة بأسلوب البطة
جزء من قسم البرمجة كائنية التوجه في رحلة 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 عبر الإنترنت