PythonGuide/OOP Inheritance

من PFWiki

اذهب إلى: تصفح, البحث

الوراثة

العلم كله مبنى على الوراثة والإكمال من حيث انتهى الآخرون

تخيل ان عندنا كلاس Human كالتالى

class Human(object):
 
    def __init__(self, name, sex):
        self._name=name
        self._sex=sex
 
    def _set_name(self, name):
        self._name=name
 
    def _set_sex(self, sex):
        self._sex=sex
 
    name=property(fget=lambda self:self._name, fset=_set_name)
    sex=property(fget=lambda self:self._sex, fset=_set_sex)


وعندنا كلاس Employer كالتالى

class Employer(object):
 
    def __init__(self, name, sex, salary):
        self._name=name
        self._sex=sex
        self._salary=salary
 
    def _set_name(self, name):
        self._name=name
 
    def _set_sex(self, sex):
        self._sex=sex
 
    def _set_salary(self, salary):
        self._salary=salary
 
 
    name=property(fget=lambda self:self._name, fset=_set_name)
    sex=property(fget=lambda self:self._sex, fset=_set_sex)
    salary=property(fget=lambda self: self._salary, fset=_set_salary)


اكيد لاحظت ان ال Employer هو Human ولكن مش فيه زيادة عن ال Human غير ال salary attribute و ال salary setter وال salary property

يعنى نقدر نقول ال Employer is-a human

   فكل اللى عليك انك تحسن الكود بحيث ان ال Employer يورث كل الصفات + الميثودز الموجودة بال Human  ويضيف عليه المميزات الخاصة بيه زى ال salary كالتالى مثلا
class Employer(Human):
    def __init__(self, name, sex, salary):
        Human.__init__(name, sex)
        self._salary=salary
 
    def _set_salary(self, salary):
        self._salary=salary
 
    salary=property(fget=lambda self: self._salary, fset=_set_salary)


تعالى نتكلم بمثال اوضح وقريب من العالم الحقيقى بعض الشئ وعلى المثال السابق إنسان وموظف ومدير الموظف ماهو إلا إنسان والمدير ماهو إلا انسان مش كدا ؟ تعالى الأول نعرف ال Human class بتاعنا

class Human(object):
 
    def __init__(self, name, color, sex):
 
        #Data members..
        self.__name=name
        assert sex in Gender.Options #Male or Female only.
        self.__sex=sex
        self.__color=color
 
    #getters/setters...
    def getName(self):
        return self.__name
 
 
    def setName(self, value):
        self.__name = value
 
 
    def getSex(self):
        return self.__sex
 
 
    def setSex(self, value):
        self.__sex = value
 
 
    def getColor(self):
        return self.__color
 
 
    def setColor(self, value):
        self.__color = value
 
    #properties...
    name = property(getName, setName, None, "Gets/Sets name.")
 
    sex = property(getSex, setSex, None, "Gets/Sets sex.")
 
    color = property(getColor, setColor, None, "Gets/Sets color.")
 
    __str__=lambda self: "<Human object: %s >"%self.__name
 
    __unicode__=__str__
 
    #methods..
    def eat(self):
        #Eating
        pass
 
    def drink(self):
        #Drinking
        pass
 
    def sleep(self):
        #Sleeping
        pass

هنا عرفنا صنف جديد بيعبر عن الإنسان وليه متغيرات داخلية زى الإسم واللون والنوع وبعض الميثودز لمعالجتهم وميثودز اخرى مثل eat, drink, sleep

لاحظ ان النوع لازم يكون موجود فى Gender.Options المعرفة كالتالى

class Gender(object):
    Male, Female="Male", "Female" #0, 1 whatever!
    Options=(Male,Female)


الإسلوب دا يقدر يفيدك لما تيجى عايز تعمل type لنوع صامت او جامد مثلا النوع او الألوان وهكذا لاحظ ال __str__ دى magic method بيتم استدعائها عند استدعاء print او حتى ال casting بإستخدام str() لاحظ اننا خلينا __unicode___ نفس المعنى من str (ويفضل انك تستخدم ال unicode على طول الأبلكيشن بتاعك) تقدر تعرفهم اكيد كالتالى

def __str__(self):
	....
 
def __unicode__(self):
	return self.__str__()


نيجى للموظف

class Employer(Human):
 
    def __init__(self, name, color, sex, salary, firm):
       #Construct the human with (name, color, sex)
        Human.__init__(self, name, color, sex)
        #Superize it :)
        #super(Employer, self).__init__(name, color, sex)
 
        self.__salary=salary
 
        self.__firm=firm
 
    def getFirm(self):
        return self.__firm
 
 
    def setFirm(self, value):
        self.__firm = value
 
 
    firm = property(getFirm, setFirm, None, "Gets/Sets the firm.")
 
    def getSalary(self):
        return self.__salary
 
 
    def setSalary(self, value):
        self.__salary = value
 
 
    salary = property(getSalary, setSalary, None, "Gets/Sets salary.")
 
    __str__=lambda self: "<Employer object:(%s, %d) >"%(self.getName(), self.salary) #super(Employer, self)
 
    def eat(self):
        print "This is my break (eat or having fun hummm?"
 
    def sleep(self):
        print "Hi, it's me sleeping!"


هنا بننشئ كلاس جديد مشتق من ال Human وبنجهزه بالبيانات الخاصة بال Human (اسم ولون ونوع) والبيانات الخاصة بالموظف (المرتب والشركة) ومتغيرات تعالج الحالة اعدنا تعريف بعض الميثودز(الطرق) الخاصة بال Human بمعنى انهم اصبحت overriden

نيجى للمدير ومالمدير الا موظف ولكن له صلاحيات اعلى زى مثلا اعطاء علاوة او فصل موظف وهكذا

class Manager(Employer):
 
    def __init__(self, name, color, sex, salary, firm):
        #Employer.__init__(self, name, color, sex, salary, firm)
        super(Manager, self).__init__(name, color, sex, salary, firm)
        #print self.__dict__
        #{'_Human__color': 'white', '_Employer__salary': 200000, '_Human__name': 'Wael', '_Employer__firm': 'Sun', '_Human__sex': 'Male'}
 
    def raiseSalaryOf(self, emp, theraise):
        assert (isinstance(emp,Employer) and emp.firm==self.firm)
        emp.salary += theraise


لاحظ انك لو طلبت .__dict__ لأى كلاس هيعرضلك قاموس dictionary فيه القيم اللى وراثها من المتغيرات الداخلية والمقطع الأول منها بيعبر عن منين موروثة

تعالى ننفذ عالمنا الصغير دا كتطبيق سريع

if __name__=="__main__":
 
    ahmed=Employer("ahmed", "white", Gender.Male, 50000, "Google")
    omar =Employer("omar", "black", Gender.Male, 40000, "Sun")
    tina =Employer("christina", "white", Gender.Female, 50000, "Google")
    emps=(ahmed, omar, tina)
    wael=Manager("Wael", "white", Gender.Male, 200000, "Sun")
    wael.raiseSalaryOf(omar, 9000)
 
 
    print issubclass(Employer, Human)
    print isinstance(ahmed, Human) #Ahmed is a Human..
    print Human.__bases__ #inherits object.
    print Manager.__bases__ #Inherits Employer..


لاحظ ان issubclass(C, B) بتسأل هل الصف C مشتق من B او لأ لاحظ isinstance(object, Type) بتسأل هل ال object دا تم انشاءه من الصف Type او لأ لاحظ ان __bases__ بتعبر عن الأب (او الأباء لو ورثت من اكتر من صف) احنا استخدمنا assert فى كذا جزئية لكن ايه هى assert ? Assert بتفيد فى عمل تصحيح سريع بحيث انك تضمن عدم التنفيذ فى حال وجود خطأ

امتة استخدم ASSERT ? استخدامها مقترن بحالة التطوير والمحل مثلا مش هتعمل كود فيه assert statement للمستخدم النهائى ، لكن ممكن تحطها فى مكتبة هيستخدمها مطور (هيراعى المتطلبات مظبوط) غير كدا استخدم ال Exceptions, Errors

الوراثة المتعددة

class Wolf(object):
    def __init__(self):
        self.__bite=True
 
 
    can_bite=lambda self:self.__bite
 
    def fullmoon(self):
        print "Wooooooooooooooooooooooooo"
 
    def bite(self, h):
        print "I'm cursed"
 
class Werewolf(Human, Wolf):
 
    def __init__(self, name, color, sex):
        Human.__init__(self, name, color, sex)
        Wolf.__init__(self)

تابع مثالنا السابق هنا عندنا صف بإسم wolf وصف بإسم مستذئب بيورث الإنسان والذئب

    yasser=Werewolf("yasser", "black", Gender.Male)
    print yasser.__dict__
    print "Can bite? ", yasser.can_bite()
    yasser.bite(ahmed)
    print Werewolf.__bases__

الناتج

{'_Human__color': 'black', '_Wolf__bite': True, '_Human__name': 'yasser', '_Human__sex': 'Male'}
Can bite?  True
I'm cursed
(<class '__main__.Human'>, <class '__main__.Wolf'>)

الأباء للمستذئب زى ماشفت فى ناتج __bases__

(<class '__main__.Human'>, <class '__main__.Wolf'>)


→ OOP Basics OOP inheritance Exceptions Errors ←
أدوات شخصية