Module 7 Essential of Object-Oriented Programming
برنامه ای بنویسید تعداد نام یک لیست را از کاربر پرس یده و س پس نامها را بخوان د و در انته ا لیس ت مرتب شده اسامی را چاپ کند؟
using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string[] names; int num; Console.Write("How many names?"); string tempstr=Console.ReadLine(); names=new string[Int32.Parse(tempstr)]; for (int i = 0; i < names.Length;i++) names[i]=Console.ReadLine(); for (int i = 0; i < names.Length;i++) for (int j = i; j < names.Length; j++) {//compare is case sensitive (Upeercase are greater) if (string.Compare(names[i].ToLower(), names[j].ToLower()) > 0) { tempstr = names[i]; names[i] = names[j]; names[j] = tempstr; } } foreach(string temp in names) Console.Write(" {0}",temp); Console.ReadKey(); } } }
زبان #Cاز زبانهای شیئی گرا می باشد. زبانهای شی ئی گرا بر ا ساس کل سها ساخته شده اند. عم ل طبق ه بندی توس ط کلس ها انجام می شود. ب ه عنوان مثال تمام اتومبیلها دارای رفتار (مث ل راندن ،توق ف).... ،و خاصیتهای مشترکی(دارای چهار چرخ ،دارای موتور) هستند .بنابراین می توان تمام آنها را در یک کلس به نام Carقرار داد. از کلس ها تنه ا برای طبقه بندی اشیاء حقیق ی اس تفاده نم ی شود .بلک ه موجودیت
شیئ یک نمونه از یک کلس را شئی گویند. در مثال قبل در صورتی که واژه carبه یک طبقه از اشیاء اشاره کند منظور ما کلس می باشد .و در صورتی که واژه carبه ی ک خودرو خاص اشاره کند منظور ما یک شیئی می باشد. در برنام ه نویس ی کلس را ب ا کلمه کلیدی classمعرف ی م ی کنن د و یک نمونه خاص از یک کلس را instanceآن کلس می نامند.
سه مشخصه اشیاء ( )1Identityهویت) :ویژگی که توسط آن می توان یک شیئی را از اشیاء دیگر متمایز نمود هویت نامیده می شود. مثال :دو همس ایه دارای دو خودرو از یک مدل و ب ا مشخص اتی کامل شبی ه ب ه هم هس تند .ای ن دو خود رو توس ط ویژگی پلک کامل قابل تمیز می باشند. هر شیئی در داخل یک برنامه دارای آدرسی خاص می باشد که توسط این آدرس از سایر اشیاء قابل تشخیص است. بعض ی از کلس ها دارای صفاتی ()Attribute هستند که توسط آنها نیز می توان اشیاء را از ه م تشخی ص داد .مثل شماره کارمندی،
: )2Behaviorهر شیئ ی ،ی ک واس ط با اس تفاده از تعدادی عمل ()operation فراه م م ی آورد .بعض ی از این اعمال عم ل بروزرسانی و پردازش داده های داخل شیئی را انجام می دهند .و بعضی دیگ ر عموم ی ت ر بوده و وظیفه مندی کلی در کل سیستم را بر عهده دارند.
: )3Stateهر شئی حاوی مقداری داده می باشد .مقاد یر داده ای که در داخل یک شیئی نگهداری می شوند حالت آن شئ ی را تعیی ن م ی کنند .کلسها را معمول به گونه ای طراحی می کنند که متغیی ر های آنه ا از خارج کلس قابل دسترس نبوده و تنها از طریق متدهای داخل کلس بتوان داده ها را تغییر داد.
Structها معمول فاق د مت د م ی باشند ولی کلسها دارای متد هستند. در #Cانواع ارائ ه شده توس ط کلسها Refrence Typeنامیده می نوعهای شوند. بر خلف کلسها معمول اطلعات داخل ساختارها از بیرون قابل دسترسی می باشند. Structها Value Typeهستند.
Refrence Type
Value Type
نوع داده هایی که در پائین ترین سطح برنام ه ه ا معرف ی م ی شوند Values Typeنامیده م ی شوند .و در حقیقت المانهای ی هس تند ک ه س ازنده سایر موجودیتها نرم افزاری می باشند. Refrence Typeها عموما در سطح بالتر نرم افزار دیده م ی شون د و بر اساس موجودیتهای نرم افزاری کوچکتر ساخته شده اند.
کپسوله سازی کپسوله سازی دارای دو جنبه می باشد : ترکی ب داده ه ا و مت د ه ا در داخ ل ی ک موجودیت واحد کنترل دسترسی به اعضاء موجودیت
ه ر شیئ ی دارای داده های اختصاصی مربوط به خود می باشد.و تساوی متغییرها به معنی یکی بودن اشیاء نیست.
در صورتی که بخواهیم مقادیری عددی یکساتی را در داخل تمام اشیاء یک کلس ب ه اشتراک بگذاریم .ذخیره این مقدار در تمام اشیاء ایده مناسبی نیست.
دلیل نامناسب بودن ایده تکرار یک متغییر باعث می شود یک داده تکراری در تمام اشیاء تکرار شده و سبب اتلف حافظه گردد. در ص ورتی ک ه بخواهیم مقدار تکراری را اص لح کنی م این مقدار در تمامی اشیاء باید اصلح شود.
راه حل برای آنکه بتوانیم یک داده مشترک تعریف کنیم نبای د آنرا در س طح اشیاء ب ه اشتراک بگذاریم بلک ه عنص ر مشترک بای د در س طح کلس به اشتراک گذاشته شود.
برای ب ه اشتراک گذاشت ن داده ها در سطح کلس با ید داده ها را به صورت Staticتعریف نمود. داده تعری ف شده ب ه صورت staticدر داخل کلس مربوط به کلس می باشد و حتی اگر از کلس مورد نظر شیئی ساخته نشود باز ه م ای ن متغیی ر قابل دسترس خواهد بود.
ب ا تعری ف متغییره ا در س طح کلس این نیاز بوجود می آید که بتوان متد های کلس را نیز در سطح کلس فراخوانی نمود .این هدف با استفاده از متد های نوع staticقابل دستیابی می باشد. مت د های اس تاتیک را ب ا نام کلس می توان فراخوانی نمود و فراخوانی آنها از طریق نام شیئ ی امکان پذی ر نم ی باشد .بنابرای نمی توان برای فراخوان ی متدهای استاتیک از عملگر thisاستفاده نمود. متد های غیر استاتیک را نمی توان در سطح کلس فراخوانی نمود. ی ک مت د اس تاتیک امکان دس ترسی ب ه متغییر ها و متدهای غیر استاتیک را ندارد .بنابراین
با تعریف داده های استاتیک از نوع Privateو تعریف متد های استاتیک نوع Publicمی توان به داده های استاتیک دسترسی داشت.
برنامه زیر تعداد اتومبیلهای یک مسابقه را محاسبه می کند:
namespace ConsoleApplication1 { class carsinrace { private static int numstatic; private int num; public static int getnumber() { return numstatic; } public void inc() { numstatic++; num++; } } class Program { static void Main(string[] args) { carsinrace rd = new carsinrace(); rd.inc(); carsinrace pk = new carsinrace(); pk.inc(); Console.WriteLine("value of num is {0}",carsinrace.getnumber()); Console.ReadKey(); } }}
متدهای استاتیک می توانند با استفاده از ارجاع به یک شیئ به .تمام اعضاء آن دسترسی داشته باشند class Time { ... public static void Reset(Time t) { t.hours = 0; // Okay t.minutes = 0; // Okay hour = 0; // compile-time error minute = 0 // compile-time error } private int hour, minute; }
یک کلس نمونه class BankAccount { public void Withdraw(decimal amount) { ... } public void Deposit(decimal amount) { ... } private decimal balance; private string name; }
: مثال class BankAccount { public void Deposit(decimal amount) { balance += amount; } private decimal balance; }
class BankRobber { public void StealFrom(BankAccount underAttack) { underAttack.balance -= 999999M;//Fail } }
:مثال برای داده استاتیک class BankAccount { public void Deposit(decimal amount) { ... } public static void Main( ) { ... } ... private decimal balance; private static decimal interestRate; }
دو کلس زیر معادل یکدیگر هستند class BankAccount { ... decimal balance; } class BankAccount { ... private decimal balance; }
Value تولید یک متغییر از نوع type struct Time { public int hour, minute; } class Program { static void Main( ) { Time now; now.hour = 11; now.minute = 59; ... } }
زمانی که یک متغییر از نوع Value Typeمعرفی می شود در حقیقت فضای لزم در حافظه برای نگهداری آن ایجاد م ی شود .بنابرای ن در مثال قب ل ب ا تعریف متغییر nowبلفاصله متغییر قابل استفاده خواهد بود. با ایجاد یک متغییر از نوع Value Typeحتما باید ابتدا به آنها مقدار اولیه نسبت داده شود تا بتوان آنها را خواند. حوزه متغیی ر های از نوع Value Typeمحدود به بلوک ی اس ت ک ه در داخ ل آ ن تعری ف شده ان د و با خروج از بلوک از بین خواهند رفت.
Refrence ایجاد یک متغییر از نوع type class Time // NOTE: Time is now a class { public int hour, minute; } class Program { static void Main( ) { Time now; now.hour = 11; now.minute = 59; ... } }
ب ا معرف ی ی ک متغییر از نوع Refrence Type فقط یک اشاره گر تولید خواهد شد که قابلیت اشاره ب ه متغی ر مربوط ه را خواهد داشت .در مثال قبلی با تعریف متغییر Nowشیئی از نوع Timeنخواهیم داشت .و کد ارائه شده با پیام خطای error CS0165: Use of possibly 'unassigned local variable 'now روبرو خواهد شد.
اصلح کد برای برطرف نمودن مشکل بای د ب ا اس تفاده از عملگر New یک شیئی تولید کنیم که Nowبه آن اشاره کند .بنابراین: class Program { ) (static void Main { ;) (Time now = new Time ;now.hour = 11 ;now.minute = 59 ... } }
آیا کد زیر به درستی اجرا خواهد شد class Program { static void Main( ) { Time now = new Time( ); Console.WriteLine(now.hour); // writes 0 Console.WriteLine(now.minute); // writes 0 ... } }
عملگر this عملگ ر thisبه شیئ ی اشاره م ی کن د ک ه متد مربوط ه از داخ ل آ ن فراخوان ی شده است. this یک ی از کاربردهای عملگر Call Chainingمی باشد.
class BankAccount { )public void SetName(string name { ;name = name } ;private string name } ه ر دو شناس ه Nameبه عنوان پارامت ر شناخت ه می شوند و هیچ تاثیری بر روی شناسه nameخصوصی ا ین کلس ندارند .برای حل ا ین مش کل دو راه حل وجود دارد .ا) تغییر نام پارامتر )2استفاده از شناسه this
: مثال class Book { public Book SetAuthor(string author) { this.author = author; return this; } public Book SetTitle(string title) { this. title = title; return this; } private string author, title; }
class Usage { static void Chained(Book good) { good.SetAuthor(“Fowler”).SetTitle(“Refactoring”); } static void NotChained(Book good) { good.SetAuthor(“Fowler”); good.SetTitle(“Refactoring”); } }
ایجاد کلسهای تودرتو
در داخل یک کلس می توان هر کدام از انواع زیر را تعریف نمود.
Class Struct Interface Enum Delegate
تعریفBank داخل کلسAccount فرض بر آنست که :شده است // Program.cs class Program { static void Main( ) { Account yours = new Account( ); // compile-time error } } // end of file c:\> csc Program.cs error CS0234: The type...'Account' does not exist in the class...'Program'
ای ن ک د ب ه درستی اجرا:مثال خواهد شد چرا؟ class Bank { class Account( ) { ... } Account OpenAccount( ) { return new Account ( ); } }
مزایای استفاده از کلسهای تودرتو به کمک آنها می توان تعداد نامهای موجود به صورت Globalرا کاهش داد. می توان کلسها را دسته بندی نمود به عنوان مثال می توان بجای BankAccountاز اسم Bank .Accountاستفاده نمود.
کلسهای تودرتو را می توان به صورت عمومی یا خصوصی تعریف نمود.
class Bank { private class AccountNumberGenerator( ) { ... } } class Program { static void Main( ) { // Compile time error Bank.AccountNumberGenerator variable; } }
: مثال.کلسهای نوع خصوصی تنها در کلس حاوی آنها قابل استفاده خواهد بود class Bank { public class Account { public void Setup( ) { NumberSetter.Set(this); balance = 0M; } private class NumberSetter { public static void Set(Account a) { a.number = nextNumber++; } private static int nextNumber = 2311; } private int number; private decimal balance; } } دسترسی داشتهNumberSetter می تواند بهAccount.Setup .باشد
ارث بری
وراثت وراث ت رابط ه ای ک ه در س طح کلس مشخ ص می شود. ی ک کلس جدی د م ی توان د از کلس قدیم ی مشتق شود. کلس Musicianکلس پایه و Violin Playerکلس مشتق شده نامیده می شود .کلس مشتق شده تمام خص وصیتهای کلس پای ه را ب ه ارث م ی برد مثل اگر کلس Musicianدارای متد TuneYourInstrument باش د تمام کلس های مشت ق شده نی ز دارای ای ن متد خواهند بود. هر تغییر در کلس پایه در تمام کلسهای مشتق شده منعکس خواهد شد .به عنوان مثال اضافه نمودن یک متد به کلس پایه باعث اضافه شدن متد جدید به تمام کلسهای مشتق شده خواهد شد.
سلسله مراتب کلسها
وراثت چندگانه
وراث ت چن د گانه در #Cمحدود شده است .هر کلس می تواند حداکثر از یک کلس و تعداد نامحدود Interfaceمشتق شود.
(Polymorphism) چند شکلی
Abstract Classes
Interface
واسط و Abstract classاز آن بابت که از هیچ کدام نمی توان نمونه شیئ ساخت مشابه هم هس تند .ام ا تفاوت آنه ا در آ ن اس ت که Abstract classمی توان د حاوی کد پیاده سازی باشد ولی در یک واسط به هیچ عنوان امکان پیاده سازی وجود ندارد .و در واسطها فقط متدها معرفی می شوند و نمی توان متغییر تعریف نمود .و به عبارت دیگر واسط کلی تر از Abstract Classاست. زمان ی ک ه از ی ک واس ط مشت ق م ی گیریم گفته می شود که آنرا پیاده سازی نموده ایم. زمان ی ک ه از ی ک کلس حقیق ی یا Abstract مشتق می سازیم می گوییم کلس مربوطه
مقید سازی زودهنگام و دیر هنگام