۱۲/۰۲/۱۳۸۸

برنامه نویسی شیء گرا - قسمت چهارم > وراثت


همانطور که در دنیای واقعی برخی مفاهیم از مفاهیم کوچکتر بوجود می آیند یا برخی اشیاء ویژگیهای برخی دیگر را به ارث میبرند و یا تکامل یافته ی اشیای دیگرند، در برنامه نویسی شیء گرا هم این امکان وجود دارد و این مهم ترین بخش از برنامه نویسی شیء گراست.

در قسمت اول، مفهوم نقطه در صفحه را تعریف کردیم. با استفاده از آن به راحتی میتوان مفهوم نقطه در فضا را هم تعریف کرد. دقت کنید

class Point(object):
   
    def __init__(self,x,y):
        self.x=x
        self.y=y

    def __str__(self):
        return str(self.x)+' '+str(self.y)


#instead on inheriting object
#this time I inherit Point class
class Point3D(Point):
    '''
    represents a point in the space
    inherits Point class
    '''

    #overriding constructor method
    def __init__(self,x,y,z):
        #calling constructor of supper class
        #from this instance (self)
        super(Point3D,self).__init__(x,y)
        self.z=z

    #overriding __str__ method
    def __str__(self):

        #calling __str__ method of
        #the base class (Point)
        #it will return str(self.x)+' '+str(self.y)
        XandY=Point.__str__(self)

        return XandY+' '+str(self.z)

    #this is a new method I add for
Point3D
    def vector_len(self):
        '''
        returns the length of the vector
        which represents this point
        '''
        from math import sqrt
        x,y,z=self.x,self.y,self.z
        return sqrt(x**2+y**2+z**2)


ابتدا بجای object نام کلاسی که از آن ارث میبریم را مینویسیم. با همین کار ساده میتوانیم از تمامی ویژگیها و متودهای کلاس پایه (base class) در این کلاس استفاده کنیم. (به کلاس پایه superclass نیز میگویند)
در مواقعی خاص برای صدا زدن متودهای کلاس پایه از تابع super استفاده میکنیم. این تابع همواره دو ورودی میگیرد که اولی نام کلاس و دومی نمونه ای از کلاس است که تابع را صدا میزند (همان self)
اگر متودی همنام با یکی از متودهای کلاس پایه تعریف کنیم جایگزین آن در این کلاس میشود. یعنی اگر از این کلاس صدا زده شود متود جدید فراخوانده میشود و نه متود همنام آن در کلاس پایه! به این کار override کردن یک متود میگویند. در مثال بالا تابع سازنده و تابع __str__ "اوور راید" شده اند.



>>> p=Point3D(1,2,3)
>>> print p
1 2 3
>>> p.x
1
>>> p.z
3
>>> p1=Point(4,5)
>>> p1.x
4
>>> print p1
4 5
>>> p.vector_len()
3.7416573867739413
>>> Point3D.__doc__
'\n    represents a point in the space\n    inherits Point class\n    '





یک مثال هم از اشیاء:

در این مثال از ماژول turtle استفاده میشود که خارج از بحث این قسمت است. برای آشنایی با این ماژول به اینجا و برای آشنایی بیشتر به اینجا مراجعه کنید.

میخواهیم مفهوم توپ در صفحه را تعریف کنیم. برای اینکار به سادگی میتوان توپ را حالت خاصی از یک نمونه از کلاس turtle.Turtle در نظر گرفت که به شکل توپ(دایروی) درآمده است. در واقع برای تعریف توپ این کلاس را به ارث میبریم.

#importing Turtle class
from turtle import Turtle

#inheriting from Turtle class
class Ball(Turtle):
    '''represents a 2D ball on the screen'''

    #overriding Turtle's constructor method
    def __init__(self,radius,color='black'):
        '''
        radius is the radius of the ball in pixels
        color is name of the color of the ball
        (optional argument)
        '''
        #first we have to initialize the associated
        #Turtle instance for this ball
        super(Ball,self).__init__()
        #the above line is nearly the
        #same as Turtle.__init__(self)


        #2D balls are circle shaped :D
        self.shape('circle')

        #initializing size and color attributes
       
        #this float division here is because
        #turtlesize is nearly one tenth of
        #its real value in pixels
        self.turtlesize(radius/10.)
        self.color(color)

        #I want my ball to leave

        #no trace on the screen
        self.penup()

    def move(self,teta=0,step=10):
        '''
        moves the ball 'step' points on 
        'teta' direction
        (both arguments are optional)
        '''
        #setting the angle of the ball to teta
        self.setheading(teta)
        #forwarding step points on

        #the new direction (teta)
        self.forward(step)



در مثال بالا توپ بسیار ساده تعریف شد و تنها یک متود برای حرکت آن تعریف کردیم. البته تمامی توابع کلاس Turtle نیز برای این توپ قابل استفاده هستند. (به ارث برده شده اند)

>>>
>>> myball=Ball(20,'blue')
>>> myball.move()
>>> myball.move(teta=45)
>>> myball.move(step=100,teta=60)
>>> myball.speed('lowest')
>>> myball.forward(-100)
>>> myball.speed(1)
>>> myball.move(45,45)
>>> myball.position()
(48.89,38.89)
>>> myball.circle(30)
>>>




در قسمتهای بعدی بیشتر درمورد وراثت در پایتون توضیح خواهم داد. برای اطلاعات بیشتر در این مورد به فارسی میتوانید به اینجا یا اینجا و به انگلیسی به اینجا مراجعه کنید.
در ضمن اطلاعات بیشتر درمورد متود super در سایت رسمی پایتون اینجا موجود است.

موفق باشید ☺

‏۲ نظر:

  1. سلام محسن جان کارت خیلی زیباست این که داری آموزش میدی.حتما استفاده میکنم و سعی میکنم به دوستان وبلاگتو معرفی کنم.موفق باشی

    پاسخحذف