تعريف البروتوكولات
جزء من قسم البرمجة كائنية التوجه في رحلة Swift على Coddy. الدرس 27 من 57.
يسرد البروتوكول المتطلبات (الأساليب والخصائص) من دون تنفيذها. يتوافق النوع مع البروتوكول من خلال توفير كل متطلب، وبعد ذلك يمكن استخدامه أينما كان البروتوكول متوقعًا:
protocol Describable {
func describe() -> String
}
struct Book: Describable {
let title: String
func describe() -> String { "Book: \(title)" }
}
print(Book(title: "Dune").describe())الناتج:
Book: Duneعلى خلاف الوراثة، يعمل البروتوكول مع الهياكل والفئات والتعدادات على حد سواء، ويمكن لنوع ما أن يتوافق مع العديد من البروتوكولات. يحدد البروتوكول فقط ما يمكن لنوع ما فعله؛ أما كل نوع فيحدد كيفية ذلك:
protocol Describable {
func describe() -> String
}
struct Point: Describable {
var x = 0, y = 0
func describe() -> String { "(\(x), \(y))" }
}
enum Level: Describable {
case low, high
func describe() -> String { self == .low ? "low" : "high" }
}
print(Point(x: 1, y: 2).describe())
print(Level.high.describe())الناتج:
(1, 2)
highتحدد متطلبات الخصائص النوع وما إذا كانت الخاصية للقراءة فقط ({ get }) أو قابلة للكتابة أيضًا ({ get set }). يمكن تلبية متطلب { get } بواسطة خاصية مخزنة أو محسوبة:
protocol Named {
var name: String { get }
}
struct User: Named {
let name: String
}
struct Planet: Named {
var number: Int
var name: String { "Planet \(number)" }
}
print(User(name: "ada").name)
print(Planet(number: 3).name)المخرجات:
ada
Planet 3إذا ادّعى نوعٌ ما توافقه لكنه لم يستوفِ أحد المتطلبات، فلن تتم ترجمته. يتحقق المترجم من كل توافق، لذا يمكن للكود الذي يستخدم البروتوكول الاعتماد عليه:
protocol Priced {
var price: Int { get }
func discounted(by percent: Int) -> Int
}
// struct Ticket: Priced { var price = 10 }
// خطأ: النوع 'Ticket' لا يتوافق مع البروتوكول 'Priced'التحدي
سهلصرّح ببروتوكول Shape يحتوي على خاصية للقراءة فقط باسم name (من النوع String) وطريقة area() تُرجع قيمة من النوع Double. اجعل البنيتين Rectangle (بعرض وارتفاع) وCircle (بنصف قطر، باستخدام 3.0 لقيمة π لتبسيط الأرقام) تتوافقان معه، مع الاسمين rectangle وcircle.
يقرأ الكود المُزوَّد أسطرًا مثل r,3,4 أو c,2، وينشئ الشكل المطابق ويطبع rectangle: 12.0.
ضع كودك في Shape.swift وRectangle.swift وCircle.swift. يحتوي main.swift على كود الإدخال/الإخراج المُزوَّد، ولا يمكن تعديله.
جرّب بنفسك
// كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
let p = line.split(separator: ",").map(String.init)
if p[0] == "r" {
let s = Rectangle(width: Double(p[1])!, height: Double(p[2])!)
print("\(s.name): \(s.area())")
} else {
let s = Circle(radius: Double(p[1])!)
print("\(s.name): \(s.area())")
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الأصناف والكائنات
العمل مع الملفاتتعريف الأصنافالأساليب وselfالمُهيِّئاتالأصناف هي مراجعمراجعة - بطاقة المكتبة4التغليف
التحكم في الوصولللقراءة فقط من الخارجحماية الحالةالمهيئات القابلة للفشلمراجعة - الحساب البنكي7تعدد الأشكال والأنواع العامة
تعدد الأشكالتحويل الأنواعالدوال العامةالأنواع العامةمراجعة - حاسبة الأشكال3الخصائص بتعمّق
الخصائص المحسوبةمراقبو الخصائصالأعضاء الثابتةالتعدادات مع الدوالمراجعة - سجل درجات الحرارة6البروتوكولات
تعريف البروتوكولاتالأنواع المتوافقةامتدادات البروتوكولاتالبروتوكولات كأنواعمراجعة - نظام الدفعتدرّب بنفسك: Playground لـ Swift