شاید اولین تفاوت مهمی که در فاکس داس و ویندوز وجود دارد همین باشد.
اما این دو واقعا چه هستند؟
در برنامه نویسی جدید تولید برنامه بدون کلاس ممکن نیست. .net بر پایه کلاسهاست و Java در درون کلاس خلاصه شده است و از آن هم بهتر:
همه چیز در Ruby شی است. حتی اعداد!


آیا کلاس و شی یکی هستند؟ خیر.
اما چرا آنها را یکی میدانند؟
چون شی از روی کلاس ساخته می‌شود. کلاس وجود خارجی ندارد و مانند این است که ما بگوییم Integer اما Object وجود خارجی دارد و مثل این است که بگوییم عدد ۲.

ساده ترین کلاس کلاسی است بدون چیزی در آن. 
و در هر کلاس مشخصه و متد وجود دارد.

کلاس می تواند از روی کلاسی دیگر ساخته شود و کلاس ساخته شده تمام خواص کلاس قبلی را دارد.

کلاس دارای دو نوع متغیر و متد از نظر دسترسی است:
عمومی Public یا Private یا خصوصی

عمومی در هر جایی خارج از کلاس قابل دسترسی است اما خصوصی فقط در سطج کلاس.

البته در جاوا نوع دیگری هم داریم که دوستانه نام دارد و هر جایی داخل یک فایل است.

خب برای ساخت یک کلاس مانند زیر عمل می کنیم:

کد:
DEFINE CLASS class1 AS CUSTOM
ENDDEFINE

در فاکس پرو این دستور کلاس شما را می سازد. که نام کلاس در اینجا class1 است و از قوانین نام گذاری متغیرها در فاکس تبعیت میکند و نوع کلاس با AS مشخص شده که در اینجا CUSTOM است. یعنی اینکه هر کلاسی از روی یک کلاس دیگر باید ساخته شود که از قبل در زبان برنامه نویسی آن تعبیه شده است. مثلا در java تمام کلاسها شاخه ای ازکلاس پایه Object هستند. 

در اینجا ما هیچ نساخته ایم فقط گفتم که شکل کلاس چگونه باشد مثل این است که نقشه یک خانه را داده باشیم اما ساخت آن:

کد:
obj1= CREATEOBJECT("class1")

حال یک چیز واقعی ساخته شد با اینکه کلاس هیچ چیزی در آن تعریف نکردیم اما تمام خواص کلاس Custom را دارد.

دقت کنید که کلاس باید داخل فایل prg تعریف شود و با دستور set procedure فایل prg معرفی شود.

تا بحال با خواسته اید که با تاریخها کار کنید؟

من در برنامه نویسی تابعی بعنوان رشته ذخیره کرده و با توابع آنها را دستکاری میکنم اما ببینید این برنامه چگونه عمل میکند:

کد:

o=CREATEOBJECT("dates")
?ShowDate(o)

FUNCTION ShowDate
    LPARAMETERS DATES
    RETURN ALLTRIM(STR(DATES.Year))+"/"+ALLTRIM(STR(DATES.Month))+"/"+ALLTRIM(STR(DATES.Day))
ENDFUNC 



**************************************************
*-- Class:        dates (d:\program files\microsoft visual foxpro 9\vcxs.vcx)
*-- ParentClass:  custom
*-- BaseClass:    custom
*-- Time Stamp:   01/21/08 11:19:11 AM
*
DEFINE CLASS dates AS custom

    Height = 33
    Width = 82
    year = 2000
    month = 1
    day = 1
   

    *-- XML Metadata for customizable properties
    _memberdata = .F.

     PROCEDURE getyear
        RETURN THIS.Year 
    ENDPROC

    PROCEDURE getmonth
        RETURN THIS.Month 
    ENDPROC

    PROCEDURE getday
        RETURN THIS.Day 
    ENDPROC

ENDDEFINE
*
*-- EndDefine: dates
**************************************************

جالبه نه؟
ارسال شی به تابع به جای چیزهایی که تا امروز ارسال کرده ایم (شاید هم قبلا کار کرده باشید)

ما این شی را ادامه خواهم داد و کاری میکنیم که شما از آن انتظار دارید! یعنی یک شی که کار توابعی که تا حال داشته ایم را انجام دهد.

بررسی چند نکته :

- اگر متغیری یا متدی در کلاس بخواهیم از تعییر مصوب بماند از کلمه کلیدی PROTECT استفاده میکنیم چرا؟

چون اگر کلاسی از روی کلاس ما ساخته شود تمام چیز ها و متدها عینا کپی می شود در این صورت ممکن است متد توسط کلاس جدید رو نویسی شود. کلاس قبلی را تغییر دادیم تا متغیرهای آن مخفی بماند.

۲ - هر گاه کلاسی ساخته شود اولین متدی که اجرا شود Init است اگر هر پارامتری به کلاس ارسال شود به این متد ارسال شده و در این متد قابل دسترسی است.

به مثال تغییر داده شده بالا نگاه کنید:
کد:
o=CREATEOBJECT("dates",2008,1,21)
?ShowDate(o)
?o.toDate()
FUNCTION ShowDate
    LPARAMETERS DATES
    RETURN DATES.julianday()
ENDFUNC 

**************************************************
*-- Class:        dates (d:\program files\microsoft visual foxpro 9\vcxs.vcx)
*-- ParentClass:  custom
*-- BaseClass:    custom
*-- Time Stamp:   01/21/08 11:19:11 AM
*
DEFINE CLASS dates AS custom
    PROTECTED year 
    PROTECTED month
    PROTECTED day
    PROTECTED DELIMETER 
    PROTECTED Date
    
    DELIMETER = "/"  && Date Delimeter
    
    PROCEDURE Init
        LPARAMETERS tnYear, tnMonth, tnDay
        THIS.Year = tnYear
        THIS.Month = tnMonth
        THIS.Day = tnDay
    ENDPROC 

    PROCEDURE getyear
        RETURN THIS.Year 
    ENDPROC

    PROCEDURE getmonth
        RETURN THIS.Month 
    ENDPROC

    PROCEDURE getday
        RETURN THIS.Day 
    ENDPROC

    PROCEDURE julianday
         RETURN SYS(11,THIS.toDate())
    ENDPROC
    
    PROCEDURE toDate
        lnPreDateFormat = SET("Date")
        SET DATE YMD
        THIS.Date=CTOD(ALLTRIM(STR(THIS.Year))+THIS.DELIMETER+ ;
            ALLTRIM(STR(THIS.Month))+THIS.DELIMETER+ ;
            ALLTRIM(STR(THIS.Day)))
        SET DATE &lnPreDateFormat
        RETURN THIS.Date
    ENDPROC 
    
ENDDEFINE
*
*-- EndDefine: dates
**************************************************
خب حال فرض می کنیم که یک Object از روی یک کلاس ساخته باشیم به اسم Obj1 میتوانیم با دستور زیر یک کپی از آدرس این شی را داشته باشیم

کد:
obj2 = obj1
یعنی اینکه علامت تساوی در شی این معنی را میدهد که میتوان دو اسم از یک شی داشت.

در مثال پست قبلی اگر اینگونه عمل کنیم:
کد:
o1 = o
میتوانیم دیگر به جای o از o1 استفاده کنیم و یک شی دارای دو اسم می شود.
کلاسها بر دو نوعند:

کلاسهای Container و ساده.

مثلا فرم یک کلاس از نوع محتوی (Container) است. که می تواند در خودش شئی را یدک بکشد.

مثلا کلاس زیر یک فرم و یک دکمه دستور دارد که این دکمه دستور در موقع تعریف کلاس با add object به آن اضافه شده است:
کد:
DEFINE CLASS newForm AS Form 

    Width = 200
    Height = 200
    Name = "c"

    ADD OBJECT command1 AS commandbutton WITH ;
        Top = 48, ;
        Left = 48, ;
        Height = 27, ;
        Width = 84, ;
        Caption = "Command1", ;
        Name = "Command1"

ENDDEFINE
به کلاس دقت کنید که چگونه شی اضافه شده دارای مشخصاتی است که با with داده شده و بین آنها کاما قرار گرفته است.
کار کردن در حالت کد کمی سخت است بهتر است من البعد در محیط ویزوال بررسی کنیم. و سپس کد تولید شده را مشاهد کنیم:

برای تولید یک کلاس از کد:

کد:
create class
استفاده می شود که پس از تایپ فرمان فوق و کلید اینتر یک پنجره باز میشود که نام کلاس و کلاسی که باید از روی آن ساخته شود (کلاس پدری) و محل ذخیره در فایل vcx یا کتابخانه کلاسها از شما خواسته می شود. (اگر کلاس پدری از نوع OleControl باشد پس از انتخاب لیست کلاسهای ویندوز نمایش داده خواهد شد )

پس از انتخاب و جایگزینی تمام چیزهای خواسته شده کلاس پیش فرض ساخته می شود.

اما کلاس پیش فرض چیست؟

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

بعد از ذخیره کلاس از منو tools/class browser را انتخاب کنید. سپس یک پنجره باز میشود روی آیکن open کلیک کرده و یک کلاس انتخاب کنید. 

باز زدن دکمه View Class code کلاسی که انتخاب کرده اید بصورت کد نمایش داده می شود.
شاید این را همه بدانند اما تذکر میدهم:

در ارجاع به شی ها هر زبانی شیوه مخصوص خود را دارد مثلا در فاکس برای دسترسی به یک دکمه دستور در یک فرم باید نام فرم و نام آن دکمه ذکر شود آن هم فقط در محدوده آن فرم. اما برای اینکه یک فرم از دیگر جاها نیز قابل دسترسی باشد باید آدرس آن در یک متغیر Public ذخیره گردد. مثلا من هنگامی که یک فرم را اجرا میکنم نام به عنوان آدرس آنرا در یک آرایه ذخیره می کنم. 

ارجاع به شی باید حتما از طریق آدرس آن صورت گیرد. آدرس مکانی از جافظه که شی در آن قرار دارد. دقیقا فرض کنید که شی مانند یک متغیر است.


اما اسامی میانبری هم وجود دارد. this به شی جاری اشاره میکند. یعنی شئی که این کد در آن قرار می گیرد. پس خارج از اشیا this معنی ندارد. 

this.parent البته من این خصیصه خوب فاکس را در کلاسهای جاوا هم پیاده سازی کردم که اشاره به کشیی دارد که این شیء درون آن شیء است و فقط هنگامی معتبر است که این شی داخل شی دیگر باشد مانند دکمه دستور در فرم.

thisform به شی فرمی اشاره میکند که کنترل در آن است تمام اشیای روی فرم به آن دسترسی دارند حتی در متدهای فرم هم معتبر است.

پس o=this یعنی یک کسی از آدرس شی فعلی در o قرار گیرد.

منبع : بخش مقالات وب سایت برنامه های بی نیاز، گردآوری شده از مجموعه مباحث تالار فاکس پرو در سایت برنامه نویس
تاریخ گردآوری و انتشار مقاله : 1387/05/01
نویسنده : رضا توکل
گردآورنده : علی محمدحسین زاده