تصميم الواجهات
جزء من قسم البرمجة كائنية التوجه في رحلة Python على Coddy. الدرس 26 من 64.
تُعرِّف الواجهة عقدًا يجب أن تلتزم به الفئات. في Python، ننشئ الواجهات باستخدام الفئات الأساسية المجرّدة، حيث تكون جميع الأساليب مجرّدة.
استورد الوحدة abc:
from abc import ABC, abstractmethodأنشئ واجهة تحتوي على أساليب مجردة فقط:
class Drawable(ABC):
@abstractmethod
def draw(self):
pass
@abstractmethod
def resize(self, width, height):
passيجب أن تكون جميع الأساليب في الواجهة مجردة - فهي تحدد ما يجب على الفئات المُنفِّذة فعله، وليس كيفية فعله.
نفِّذ الواجهة في فئة ملموسة:
class Circle(Drawable):
def __init__(self, radius):
self.radius = radius
def draw(self):
return "Drawing a circle"
def resize(self, width, height):
self.radius = min(width, height) / 2
return f"Resized circle to radius {self.radius}"أنشئ فئة أخرى تنفّذ الواجهة نفسها:
class Rectangle(Drawable):
def __init__(self, width, height):
self.width = width
self.height = height
def draw(self):
return "Drawing a rectangle"
def resize(self, width, height):
self.width = width
self.height = height
return f"Resized rectangle to {width}x{height}"استخدم الواجهة بشكل تعددي الأشكال:
shapes = [Circle(5), Rectangle(3, 4)]
for shape in shapes:
print(shape.draw())
print(shape.resize(10, 8))المخرجات:
Drawing a circle
Resized circle to radius 4.0
Drawing a rectangle
Resized rectangle to 10x8يمكنك أيضًا استخدام الواجهات كتلميحات للأنواع:
def render_shape(drawable: Drawable):
return drawable.draw()
circle = Circle(3)
print(render_shape(circle))المخرجات:
Drawing a circleالنقطة الأساسية: تحدد الواجهات ما يجب على الأصناف فعله، وليس كيفية فعله. استخدم الأصناف الأساسية المجرّدة التي تحتوي على أساليب مجرّدة فقط لإنشاء عقود واضحة يجب على الأصناف المنفِّذة اتباعها. يضمن ذلك سلوكًا متسقًا عبر التطبيقات المختلفة.
التحدي
متوسطفي هذا التحدي، ستنفّذ نظام مشغّل وسائط باستخدام الواجهات.
تحتاج إلى تعديل الملفات التالية:
playable.py- تنفيذ الفئات الأساسية المجرّدة (الواجهات)song.py- تنفيذ الفئة Songvideo.py- تنفيذ الفئة Videomediaplayer.py- تنفيذ الفئة MediaPlayer
يحتوي كل ملف على تعليقات TODO مفصّلة لإرشادك خلال عملية التنفيذ. اتبع هذه التعليقات لإنشاء نظام مشغّل وسائط متكامل مع التوريث الصحيح وتنفيذ الواجهات.
جرّب بنفسك
from song import Song
from video import Video
from mediaplayer import MediaPlayer
from playable import Playable, MediaInfo
# معالج شامل لحالات الاختبار
test_case = input()
if test_case == "default_test":
# حالة الاختبار الافتراضية من المسألة الأصلية
song = Song("Bohemian Rhapsody", "Queen", 355)
video = Video("Python Tutorial", "1080p", 1800)
player = MediaPlayer()
# اختبار مع الأغنية
player.set_media(song)
print(player.current_media.get_info())
print(player.play())
print(player.pause())
print(player.stop())
print() # سطر فارغ لسهولة القراءة
# اختبار مع الفيديو
player.set_media(video)
print(player.current_media.get_info())
print(player.play())
print(player.pause())
print(player.stop())
elif test_case == "empty_player":
# اختبار مشغل الوسائط بدون تعيين أي وسائط
player = MediaPlayer()
print(player.play()) # Should print "No media set"
print(player.pause()) # Should print "No media set"
print(player.stop()) # Should print "No media set"
elif test_case == "time_formatting":
# اختبار تنسيق الوقت في الدالة get_info()
song1 = Song("Short Song", "Artist A", 65) # 1:05
song2 = Song("Long Song", "Artist B", 3661) # 61:01
video1 = Video("Hour Video", "720p", 3600) # 60:00
print(song1.get_info())
print(song2.get_info())
print(video1.get_info())
elif test_case == "interface_compliance":
# اختبار أن Song و Video ينفذان الواجهات بشكل صحيح
song = Song("Test Song", "Test Artist", 180)
video = Video("Test Video", "480p", 240)
# التحقق من تنفيذ الواجهة
print(f"Song implements Playable: {isinstance(song, Playable)}")
print(f"Song implements MediaInfo: {isinstance(song, MediaInfo)}")
print(f"Video implements Playable: {isinstance(video, Playable)}")
print(f"Video implements MediaInfo: {isinstance(video, MediaInfo)}")
# اختبار جميع دوال الواجهة
print(song.play())
print(song.pause())
print(song.stop())
print(song.get_title())
print(song.get_duration())
print(song.get_info())
print(video.play())
print(video.pause())
print(video.stop())
print(video.get_title())
print(video.get_duration())
print(video.get_info())
elif test_case == "polymorphism":
# اختبار السلوك متعدد الأشكال مع قائمة من أنواع وسائط مختلفة
media_list = [
Song("Song 1", "Artist 1", 180),
Video("Video 1", "720p", 300),
Song("Song 2", "Artist 2", 240),
Video("Video 2", "1080p", 420)
]
player = MediaPlayer()
for media in media_list:
player.set_media(media)
print(f"Media: {media.get_title()}")
print(f"Info: {media.get_info()}")
print(f"Play: {player.play()}")
print()
elif test_case == "edge_cases":
# اختبار الحالات الحدية
empty_song = Song("", "", 0)
edge_video = Video("A" * 100, "", -10) # عنوان طويل جدًا، دقة فارغة، مدة سالبة
print(f"Empty song info: {empty_song.get_info()}")
print(f"Edge video info: {edge_video.get_info()}")
player = MediaPlayer()
player.set_media(empty_song)
print(player.play())
player.set_media(edge_video)
print(player.play())
elif test_case == "stress_test":
# تنفيذ اختبار إجهاد مع العديد من كائنات الوسائط
songs = [Song(f"Song {i}", f"Artist {i}", i * 30) for i in range(1, 101)]
videos = [Video(f"Video {i}", f"{i*10}p", i * 60) for i in range(1, 101)]
player = MediaPlayer()
# اختبار مع جميع الأغاني
for i, song in enumerate(songs):
player.set_media(song)
if i % 10 == 0: # اطبع فقط كل عاشر لتجنب الكثير من المخرجات
print(f"Playing song {i+1}: {player.play()}")
# اختبار مع جميع مقاطع الفيديو
for i, video in enumerate(videos):
player.set_media(video)
if i % 10 == 0: # اطبع فقط كل عاشر لتجنب الكثير من المخرجات
print(f"Playing video {i+1}: {player.play()}")
print("Stress test completed successfully!")يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsمعامل selfMethodsAttributesدالة البناء (__init__)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةدالة ()superإعادة تعريف الدوال (Method Overriding)الوراثة المتعددةترتيب استدعاء الدوال (Method Resolution Order)مراجعة - هيكلية الموظفين5تعدد الأشكال
مراجعة إعادة تعريف الدوالمفهوم Duck Typingالأصناف والدوال المجردةتصميم الواجهاتملخص - حاسبة الأشكالتدرّب بنفسك: مترجم Python عبر الإنترنت