240 likes | 415 Views
کپسوله سازی. دانشگاه ایلام مظفر بگ محمدی. انواع برنامه نویس ها. ایجاد کننده های کلاس کسانی که کلاسهای جدید طراحی می کنند. کلاسهایی می سازند که واسط مورد نیاز برنامه ی مشتری در آنها حداقل است و باقی چیزها پنهان شده اند. برنامه نویسهای مشتری کسانی که از کلاسها استفاده می کنند.
E N D
کپسوله سازی دانشگاه ایلام مظفر بگ محمدی
انواع برنامه نویس ها • ایجاد کننده های کلاس • کسانی که کلاسهای جدید طراحی می کنند. • کلاسهایی می سازند که واسط مورد نیاز برنامه ی مشتری در آنها حداقل است و باقی چیزها پنهان شده اند. • برنامه نویسهای مشتری • کسانی که از کلاسها استفاده می کنند. • می خواهند کاربردها را با استفاده از مجموعه ای از کلاس متعامل ایجاد کنند.
تکنیکهایOOP • طراحان کلاس برای دستیابی به اهداف خود از کپسوله سازی استفاده می کنند. • کپسوله سازی • ترکیب داده و عملگرها در یک نهاد واحد به اسم کلاس • تدارک شیوه ی دسترسی مناسب • تمرکز روی پیاده سازی • پنهان سازی اطلاعات (انتزاع یا تجرید)
ارزش کپسوله کردن • نیازی نیست که برنامه نویسهای مشتری از جزییات پیاده سازی کلاس خبر داشته باشند و تنها کافی است که نحوه ی استفاده از کلاس را بدانند. • اطلاعات مورد نیاز برنامه نویسان مشتری باید حداقل باشد. • ممکن است که پیاده سازی کلاس تغییر کند بدون اینکه تاثیری روی کاربران کلاس بگذارد.
کنترل دسترسی • کپسوله کردن با استفاده از کنترل دسترسی پیاده سازی شده است. • تفکیک واسط کلاس از پیاده سازی آن • مرز بین برنامه نویس مشتری و طراح کلاس • قسمت قابل مشاهده ی کلاس (واسط) • برنامه نویس مشتری می تواند از واسط استفاده کند اما نمی تواند آنرا تغییر دهد. • قسمت پنهان کلاس (پیاده سازی) • طراح کلاس می تواند بدون اطلاع برنامه نویسان مشتری پیاده سازی را تغییر دهد. • پیاده سازی نمی تواند توسط برنامه نویسان مشتری آسیب ببیند.
کنترل دسترسی در جاوا • دستوراتی (تغییر دهنده های قابلیت مشاهده) وجود دارند که اجازه می دهند دسترسی متدها و متغییرها کنترل شود. • قابلیت مشاهده ی عمومی: همه مخصوصا برنامه نویس مشتری می تواند به آن دسترسی داشته باشد. • واسط کلاستوسط متدهای عمومی تعریف می شود. • قابلیت مشاهده ی خصوصی: فقط توسط متدهای کلاس قابل دسترسی است. • حالت دیگر – بعداً
کلاسDate2 در این نسخه متغییرها بصورت خصوصی تعریف شده اند. public class Date2 { private String month;privateint day; privateint year; publicvoidtoString( ) { return month + “ “ + day + “ “ + year; } // setDate and monthString same as Date1 class } Any Date2 class method may use the class’ private instance variables.
مثال کنترل دسترسی در کلاس Date1 از متغییرهای عمومی استفاده کردیم. در کلاس Date2 از متغییرهای خصوصی استفاده می کنیم. publicclass Date2Demo { publicstaticvoid main( String[ ] args ){ Date2 myDate = new Date2( );myDate.month = “July”; // compiler errormyDate.day = 4; // compiler error myDate.year = 1950; // compiler error myDate.setDate( 7, 4, 1950 ); // OK – why? System.out.println( myDate.toString( )); } }
متغییرهای خصوصی • از متغییرهای خصوصی فقط داخل کلاس می توان استفاده کرد. • متغییرهای خصوصی جزییات پیاده سازی را پنهان می کنند و در راستای کپسوله کردن فعالیت می کنند. • کاربران کلاس (برنامه نویسان مشتری) به متغییرهای خصوصی دسترسی ندارند. • یک عادت برنامه نویسی خوب: • تمام متغییرها را خصوصی تعریف کنید. • در نتیجه کلاس روی چگونگی، زمان و شرط تغییر متغییرها کنترل کامل دارد.
خلا صه ی کپسوله سازی • ترکیب متدها و داده در یک کلاس • استفاده از متغییرهای خصوصی برای پنهان کردن اطلاعات • حداقل کردن واسط عمومی کلاس
تغییر و دسترسی متغییرها • ممکن است رفتار کلاس اجازه دهد که یک مقدار یک متغییر خصوصی خوانده شود یا تغییر کند. • متد دسترسی • مقدار متغییر خصوصی را بازیابی می کند. • رسم است که اسم این کلاس با get شروع شود. • متد تغییر • مقدار متغییر خصوصی را تغییر می دهد. • رسم است که اسم این کلاس با set شروع شود. • به برنامه ی مشتری اجازه می دهد که به متغییر خصوصی دسترسی غیر مستقیم داشته باشد.
متدهای تغییر و دسترسی سوال: آیا استفاده از متدهای فوق نقض غرض متغیرهای خصوصی نیست؟ خیر زیرا: • طراح کلاس است که تصمیم می گیرد به کدام متغییرها دسترسی داشته باشیم. • متد تغییر دهنده اعتبار مقدار جدید را ارزیابی می کند. سپس، تصمیم می گیرد که آیا درخواست تغییر را واقعا انجام دهد یا نه.
Date2 Accessor and Mutator public class Date2 { private String month;privateint day; // 1 - 31 privateint year; // 4-digit year // accessors return the value of private data publicintgetDay ( ) { return day; } // mutators can validate the new value publicbooleansetYear( intnewYear ){ if ( 1000 <= newYear && newYear <= 9999 ) { year = newYear; return true; } else // this is an invalid year return false; // rest of class definition follows }
احتیاط • کلاً لازم نیست که برای تمام متغییرهای خصوصی متدهای تغییر دهنده و دسترسی بنویسید. • به یاد آورید که اصل کپسوله سازی بر این است که واسط دسترسی کلاس مینیمم باشد. • وجود تعداد زیادی متد تغییر دهنده و دسترسی منجر به عدول از OOP و بازگشت به متد برنامه نویسی بر اساس رویه می شود. بعداً در این مورد بیشتر بحث خواهیم کرد.
متدهای خصوصی • متدها نیز می توانند خصوصی باشند. • نمی توان متد را از طریق برنامه ی مشتری صدا زد. • فقط توسط متدهای دیگر کلاس قابل صدا کردن است. • معمولا به عنوان متدهای کمکی برای پیاده سازی متدهای عمومی به کار می روند.
مثالی از متد خصوصی public class Date2 { private String month;privateint day; // 1 - 31 privateint year; // 4-digit year // mutators should validate the new value publicbooleansetYear( intnewYear ){ if ( yearIsValid( newYear ) ) { year = newYear; return true; } else // year is invalid return false; } // helper method - internal use only privatebooleanyearIsValid( int year ) { return 1000 <= year && year <= 9999; } }
مطالبی بیشتر درباره ی متد • کلاسهای مختلف می توانند متدهایی با اسم مشابه داشتند. • جاوا از روی شئی که متد را فراخوانی کرده است، متوجه می شود که کدام متد را اجرا کند. • مثال: Date2 birthday = new Date2( ); Dog fido = new Dog( ); System.out.println(birthday.toString( )); System.out.println(fido.toString( )); • دستور birthday.toString( )متد toString( ) تعریف شده در کلاس Date2 را فراخوانی می کند، زیرا شی birthdayاز نوع Date2 است. • دستور fido.toString( ) متد toString( ) تعریف شده در کلاس Dog را فراخوانی می کند، زیرا شی fido از نوع Dog است.
بارگذاری دوباره ی متدها • دو یا چند متد از یک کلاس می توانند اسم مشابه داشته باشند. • به این تکنیک بارگذاری دوباره متد می گویند.
بارگذاری متد setDate • متد setDate از کلاس Date2 بصورت زیر است: public booleansetDate( int month, int day, int year ) • فرض کنید که می خواهیم فقط روز و سال را دوباره تغییر دهیم. • متد دیگری به اسم setDate بصورت زیر تعریف کنید: public booleansetDate( int day, int year ) به هر حال، اسم setDate اسم مناسبی برای کاری که این متد انجام می دهد است.
Date3 Class - Overloaded setDate Method public class Date3 { private String month; private int day; // 1 - 31 private int year; // 4 digits publicboolean setDate( int newMonth, int newDay, int newYear ) { // code here } publicboolean setDate( int newDay, int newYear ); { // code here, doesn’t change month } // toString( ), monthString( ), setYear( ), etc. follow }
کلاس Date3Demo public class Date3Demo { public static void main (String[ ] args) { Date3 myDate = new Date3( ); myDate.setDate( 1, 23, 1982 ); System.out.println( myDate.toString( ) ); myDate.setDate( 4, 1999 ); System.out.println( myDate.toString( ) ); } } جاوا چگونه متوجه می شود کدام setDateرا فراخوانی کند؟
امضای متد • هر متد بصورت یکتا توسط موارد زیر مشخص می گردد: • اسم متد. • پارامترهای متد (نوع و ترتیب آنها) • به این موضوع امضا متد گفته می شود. مثالها: public booleansetDate(intnewMonth, intnewDay, intnewYear) public booleansetDate(String newMonth, intnewDay, intnewYear) public booleansetDate(intnewDay, intnewYear) public booleansetDate(intnewDay, String newMonth)
مقدار بازگشتی کافی نیست • فرض کنید می خواهیم تابع setDay() از کلاس Date3 را با مقادیر بازگشتی متفاوت بارگذاری کنیم. public void setDay( int day ) { /* code here */ } public booleansetDay( int day ) { /* code here */ } • این کار معتبر نیست، زیرا کدی که را فراخوانی می کند، ممکن است مقدار بازگشتی را در نظر نگیرد. birthday.setDay( 22 ); • کامپایلر نمی داند کدام setDay( )را فراخوانی کند.
سردرگمی کامپایلر تغییر نوع اتوماتیک متغییرها و بارگذاری دوباره ممکن است طوری با هم تعامل کنند که باعث سردرگمی کامپایلر شوند. public class X { //version 1 public void printAverage ( int a, double b) {/*code*/} //version 2 public void printAverage ( double a, int b) {/*code*/} } حال کد زیر را در نظر بگیرید: X myX = new X( ); myX.printAverage( 5, 7 ); کامپیایلر جاوا نمی تواند تصمیم بگیرد که: • 7 را به 7.0 تغییر نوع دهد و نسخه ی اول printAverageرا صدا بزند. • یا 5را به 5.0 تغییر نوع دهد و نسخه ی ذوم printAverageرا صدا بزند.