5. الفئات والكائنات
الفئة هي القالب الذي يتم من خلاله إنشاء الكائنات. ويُقال إن الكائن هو مثيل لفئة ما.
5.1. فئة كائن
برنامج (classes_01)
| # -*- coding=utf-8 -*-
class Objet:
"""une classe Objet vide"""
# any variable can have attributes by construction
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
# displays the
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# modify object
obj1.attr2+=100
# displays the
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# assigns object1 reference to object2
obj2=obj1
# modify obj2
obj2.attr2=0
# displays both objects
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)
|
ملاحظات:
- السطر 4: شكل آخر من أشكال التعليقات. يسبقه ثلاثة ""، ويمكن أن يمتد على عدة أسطر؛
- السطران 3-4: فئة كائن فارغة؛
- السطر 7: إنشاء مثيل لفئة Object؛
- السطر 17: نسخ مرجعي. المتغيران obj1 و obj2 هما مؤشران (مرجعان) إلى نفس الكائن.
النتائج
| objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]
|
5.2. فئة Person
البرنامج (classes_02)
| # -*- coding=utf-8 -*-
class Personne:
# class attributes
# undeclared - can be created dynamically
# method
def identite(self):
# a priori, uses non-existent attributes
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# attributes are public and can be created dynamically
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
# method call
print "personne={0}\n".format(p.identite())
|
ملاحظات:
- الأسطر 3-10: فئة تحتوي على طريقة؛
- السطر 8: يجب أن تحتوي كل دالة في الفئة على الكائن
self — الذي يشير إلى الكائن الحالي — كمعلمة أولى لها.
النتائج
personne=[Paul,Langevin,48]
5.3. فئة Person مع منشئ
البرنامج (classes_03)
| # -*- coding=utf-8 -*-
class Personne:
# manufacturer
def __init__(self,prenom,nom,age):
self.prenom=prenom;
self.nom=nom;
self.age=age;
# method
def identite(self):
# a priori, uses non-existent attributes
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# a Person object
p=Personne("Paul","Langevin",48)
# method call
print "personne={0}\n".format(p.identite())
|
ملاحظات:
- السطر 6: يُسمى منشئ الفئة __init__. وكما هو الحال مع الطرق الأخرى، فإن المعلمة الأولى له هي self؛
- السطر 18: يتم إنشاء كائن Person باستخدام منشئ الفئة.
النتائج
personne=[Paul,Langevin,48]
5.4. فئة Person مع فحوصات الصحة في المنشئ
البرنامج (classes_04)
| # -*- coding=utf-8 -*-
import re
# -------------------
# a proprietary exception class
class MyError(Exception):
pass
class Personne:
# manufacturer
def __init__(self,prenom="x",nom="x",age=0):
# first name must be non-empty
match=re.match(r"^\s*(\S+)\s*$",prenom)
if not match:
raise MyError("Le prenom ne peut etre vide")
else:
self.prenom=match.groups()[0]
# name must be non-empty
match=re.match(r"^\s*(\S+)\s*$",nom)
if not match:
raise MyError("Le nom ne peut etre vide")
else:
self.nom=match.groups()[0]
# age must be valid
match=re.match(r"^\s*(\d+)\s*$",str(age))
if not match:
raise MyError("l'age doit etre un entier positif")
else:
self.age=match.groups()[0]
def __str__(self):
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# a Person object
try:
p=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# another object Nobody
try:
p=Personne(" xx "," yy "," zz")
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# another person
try:
p=Personne()
print "personne={0}".format(p)
except MyError, erreur:
print erreur
|
ملاحظات:
- السطران 7-8: فئة MyError مشتقة من فئة Exception. وهي لا تضيف أي وظائف إلى الأخيرة. إنها موجودة فقط لتوفير استثناء مخصص؛
- السطر 13: يحتوي المنشئ على قيم افتراضية لمعلماته. وبالتالي، فإن العملية p = Person() تعادل p = Person("x", "x", 0)؛
- الأسطر 15–9: يتم فحص المعلمة first_name. يجب ألا تكون فارغة. إذا كانت فارغة، يتم إلقاء استثناء MyError مع رسالة خطأ؛
- الأسطر 21–25: الأمر نفسه بالنسبة لـ last_name؛
- الأسطر 27–31: التحقق من العمر؛
- السطور 33-34: تحل الدالة __str__ محل الطريقة التي كانت تسمى سابقًا identite؛
- الأسطر 38–42: إنشاء مثيل لـ Person وعرض هويته؛
- السطر 39: إنشاء مثيل؛
- السطر 40: العرض. تتطلب العملية عرض الشخص p كسلسلة. ثم يقوم مترجم Python تلقائيًا باستدعاء الطريقة p.__str__() إذا كانت موجودة. تخدم هذه الطريقة نفس الغرض الذي تخدمه الطريقة toString() في لغات Java أو .NET؛
- الأسطر 41–42: معالجة استثناء MyError المحتمل. ثم عرض رسالة الخطأ المرتبطة بالاستثناء؛
- الأسطر 44-48: نفس ما سبق بالنسبة لمثيل ثانٍ من Person تم إنشاؤه بمعلمات غير صحيحة؛
- الأسطر 50–54: نفس ما سبق بالنسبة لمثيل ثالث من Person تم إنشاؤه باستخدام المعلمات الافتراضية.
النتائج
| personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[x,x,0]
|
5.5. إضافة طريقة تعمل كمنشئ ثانٍ
البرنامج (classes_05)
| # -*- coding=utf-8 -*-
import re
# -------------------
# a proprietary exception class
class MyError(Exception):
pass
class Personne:
# class attributes
# undeclared - can be created dynamically
# manufacturer
def __init__(self,prenom="x",nom="x",age=0):
# first name must be non-empty
match=re.match(r"^\s*(\S+)\s*$",prenom)
if not match:
raise MyError("Le prenom ne peut etre vide")
else:
self.prenom=match.groups()[0]
# name must be non-empty
match=re.match(r"^\s*(\S+)\s*$",nom)
if not match:
raise MyError("Le nom ne peut etre vide")
else:
self.nom=match.groups()[0]
# age must be valid
match=re.match(r"^\s*(\d+)\s*$",str(age))
if not match:
raise MyError("l'age doit etre un entier positif")
else:
self.age=match.groups()[0]
def initWithPersonne(self,p):
# initializes the current object with a person p
self.__init__(p.prenom,p.nom,p.age)
def __str__(self):
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# a Person object
try:
p0=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p0)
except MyError, erreur:
print erreur
# another object Nobody
try:
p1=Personne(" xx "," yy "," zz")
print "personne={0}".format(p1)
except MyError, erreur:
print erreur
# another person
p2=Personne()
try:
p2.initWithPersonne(p0)
print "personne={0}".format(p2)
except MyError, erreur:
print erreur
|
ملاحظات:
- يكمن الاختلاف عن البرنامج النصي السابق في الأسطر 35-37. فقد أضفنا الطريقة initWithPerson. وتقوم هذه الطريقة باستدعاء مُنشئ __init__. وعلى عكس اللغات المُصنَّفة، لا يمكن وجود طرق تحمل الاسم نفسه ويتم تمييزها بناءً على طبيعة معلماتها أو قيمها المرجعة. ولذلك، لا يمكن وجود مُنشِئات متعددة تُنشئ الكائن من معلمات مختلفة، وفي هذه الحالة كائن من النوع Person.
النتائج
| personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[Paul,Langevin,48]
|
5.6. قائمة بكائنات Person
البرنامج (classes_06)
| # -*- coding=utf-8 -*-
class Personne:
...
# ---------------------------------- main
# create a list of person objects
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
# identity of these persons
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
|
ملاحظات:
- الأسطر 3-5: فئة Person التي سبق وصفها
النتائج
groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]
5.7. إنشاء فئة مشتقة من فئة Person
البرنامج (classes_07)
| # -*- coding=utf-8 -*-
import re
class Personne:
...
class Enseignant(Personne):
def __init__(self,prenom="x",nom="x",age=0,discipline="x"):
Personne.__init__(self,prenom,nom,age)
self.discipline=discipline
def __str__(self):
return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.discipline)
# ---------------------------------- main
# create a list of Personne objects and derivatives
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
# identity of these persons
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
|
ملاحظات:
- السطران 5-6: تم تعريف فئة Person بالفعل؛
- السطر 8: يُعلن فئة Teacher كفئة فرعية لفئة Person؛
- السطر 10: يجب أن يستدعي منشئ فئة Teacher المشتقة منشئ فئة Person الأصلية؛
- السطران 21-22: لعرض group[i]، يستخدم المترجم الطريقة group[i].__str__(). الطريقة __str__() المستخدمة هي تلك الخاصة بالفئة الفعلية لـ group[i]، كما هو موضح في النتائج أدناه.
النتائج
groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
5.8. إنشاء فئة ثانية مشتقة من فئة Person
البرنامج (classes_08)
| # -*- coding=utf-8 -*-
import re
class Personne:
...
class Enseignant(Personne):
...
class Etudiant(Personne):
def __init__(self,prenom="x",nom="x",age=0,formation="x"):
Personne.__init__(self,prenom,nom,age)
self.formation=formation
def __str__(self):
return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.formation)
# ---------------------------------- main
# create a list of Personne objects and derivatives
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
# identity of these persons
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
|
ملاحظات:
- هذا البرنامج النصي مشابه للبرنامج النصي السابق.
النتائج
groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[Steve,Boer,22,iup2 qualite]