سازنده ها (Constructors)
سازندهها متدهای خاصی هستند که وجود آنها برای ساخت اشیا لازم است. آنها به شما اجازه میدهند که مقادیری را به هر یک از اعضای دادهای یک آرایه اختصاص دهید و کدهایی که را که میخواهید هنگام ایجاد یک شیء اجرا شوند را به برنامه اضافه کنید. اگر از هیچ سازندهای در کلاستان استفاده نکنید، کامپایلر از سازنده پیشفرض که یک سازنده بدون پارامتر است استفاده میکند. میتوانید در برنامهتان از تعداد زیادی سازنده استفاده کنید که دارای پارامترهای متفاوتی باشند. در مثال زیر یک کلاس که شامل سازنده است را مشاهده میکنید:
1: using System; 2: 3: public class Person 4: { 5: public string name; 6: public int age; 7: public double height; 8: 9: //Explicitly declare a default constructor 10: public Person() 11: { 12: } 13: 14: //Constructor that has 3 parameters 15: public Person(string n, int a, double h) 16: { 17: name = n; 18: age = a; 19: height = h; 20: } 21: 22: public void ShowInformation() 23: { 24: Console.WriteLine("Name: {0}", name); 25: Console.WriteLine("Age: {0} years old", age); 26: Console.WriteLine("Height: {0}cm", height); 27: } 28: } 29: 30: public class Program 31: { 32: public static void Main() 33: { 34: Person firstPerson = new Person(); 35: Person secondPerson = new Person("Mike", 23, 158); 36: 37: firstPerson.name = "Jack"; 38: firstPerson.age = 21; 39: firstPerson.height = 160; 40: firstPerson.ShowInformation(); 41: 42: Console.WriteLine(); //Seperator 43: 44: secondPerson.ShowInformation(); 45: } 46: }
Name: Jack Age: 21 years old Height: 160cm Name: Mike Age: 23 years old Height: 158cm
همانطور که مشاهده میکنید در مثال بالا دو سازنده را به کلاس Person اضافه کردهایم. یکی از آنها سازنده پیشفرض (خطوط 12-10) و دیگری سازندهای است که سه آرگومان قبول میکند (خطوط 20- 15).
به این نکته توجه کنید که سازنده درست شبیه به یک متد است با این تفاوت که
- نه مقدار برگشتی دارد و نه از نوع void است.
- نام سازنده باید دقیقاً شبیه نام کلاس باشد.
سازنده پیشفرض در داخل بدنهاش هیچ چیزی ندارد و وقتی فراخوانی میشود که ما از هیچ سازندهای در کلاسمان استفاده نکنیم. در آینده متوجه میشوید که چطور میتوان مقادیر پیشفرضی به اعضای دادهای اختصاص داد، وقتی که از یک سازنده پیشفرض استفاده میکنید. به دومین سازنده توجه کنید. اولاً که نام آن شبیه نام سازنده اول است. سازندهها نیز مانند متدها میتوانند سربارگذاری شوند. حال اجازه دهید که چطور میتوانیم یک سازنده خاص را هنگام تعریف یک نمونه از کلاس فراخوانی کنیم.
Person firstPerson = new Person(); Person secondPerson = new Person("Mike", 23, 158);
در اولین نمونه ایجاد شده از کلاس Person از سازنده پیشفرض استفاده کردهایم چون پارامتری برای دریافت آرگومان ندارد. در دومین نمونه ایجاد شده، از سازندهای استفاده میکنیم که دارای سه پارامتر است. کد زیر تأثیر استفاده از دو سازنده مختلف را نشان میدهد :
firstPerson.name = "Jack"; firstPerson.age = 21; firstPerson.height = 160; firstPerson.ShowInformation(); Console.WriteLine(); //Seperator secondPerson.ShowInformation();
همانطور که مشاهده میکنید لازم است که به فیلدهایشی ای که از سازنده پیشفرض استفاده میکند مقادیری اختصاص داده شود تا اینشی نیز با فراخوانی متد ShowInformation() آنها را نمایش دهد. حال به شی دوم که از سازنده دارای پارامتر استفاده میکند توجه کنید، مشاهده میکنید که با فراخوانی متد ShowInformation() همه چیز همانطور که انتظار میرود اجرا میشود. این بدین دلیل است که شما هنگام تعریف نمونه و از قبل مقادیری به هر یک از فیلدها اختصاص دادهاید بنابراین آنها نیاز به مقدار دهی مجدد ندارند مگر اینکه شما بخواهید این مقادیر را اصلاح کنید.
اختصاص مقادیر پیشفرض به سازنده پیشفرض
در مثالهای قبلی یک سازنده پیشفرض با بدنه خالی نشان داده شد. شما میتوانید به بدنه این سازنده پیشفرض کدهایی اضافه کنید. همچنین میتوانید مقادیر پیشفرضی به فیلدهای آن اختصاص دهید.
public Person() { name = "No Name"; age = 0; height = 0; }
همانطور که در مثال بالا میبینید سازنده پیشفرض ما چیزی برای اجرا دارد. اگر نمونهای ایجاد کنیم که از این سازنده پیشفرض استفاده کند، نمونه ایجاد شده مقادیر پیشفرض سازنده پیشفرض را نشان میدهد.
Person person1 = new Person(); person1.ShowInformation();
Name: No Name Age: 0 years old Height: 0cm
استفاده از کلمه کلیدی this
راهی دیگر برای ایجاد مقادیر پیشفرض استفاده از کلمه کلیدی this است. مثال زیر اصلاح شده مثال قبل است و نحوه استفاده از 4 سازنده با تعداد پارامترهای مختلف را نشان میدهد.
1: using System; 2: 3: public class Person 4: { 5: public string name; 6: public int age; 7: public double height; 8: 9: public Person() 10: : this("No Name", 0, 0) 11: { 12: } 13: 14: public Person(string n) 15: : this(n, 0, 0) 16: { 17: } 18: 19: public Person(string n, int a) 20: : this(n, a, 0) 21: { 22: } 23: 24: public Person(string n, int a, double h) 25: { 26: name = n; 27: age = a; 28: height = h; 29: } 30: 31: public void ShowInformation() 32: { 33: Console.WriteLine("Name: {0}", name); 34: Console.WriteLine("Age: {0} years old", age); 35: Console.WriteLine("Height: {0}cmn", height); 36: } 37: } 38: 39: public class Program 40: { 41: public static void Main() 42: { 43: Person firstPerson = new Person(); 44: Person secondPerson = new Person("Jack"); 45: Person thirdPerson = new Person("Mike", 23); 46: Person fourthPerson = new Person("Chris", 18, 152); 47: 48: firstPerson.ShowInformation(); 49: secondPerson.ShowInformation(); 50: thirdPerson.ShowInformation(); 51: fourthPerson.ShowInformation(); 52: } 53: }
Name: No Name Age: 0 years old Height: 0cm Name: Jack Age: 0 years old Height: 0cm Name: Mike Age: 23 years old Height: 0cm Name: Chris Age: 18 years old Height: 152cm
ما چهار سازنده بری اصلاح کلاسمان تعریف کردهایم. شما میتوانید تعداد زیادی سازنده برای مواقع لزوم در کلاس داشته باشید. اولین سازنده یک سازنده پیشفرض است. دومین سازنده یک پارامتر از نوع رشته دریافت میکند. سومین سازنده دو پارامتر و چهارمین سازنده سه پارامتر میگیرد. به چارمین سازنده در خطوط 29-24 توجه کنید. سه سازنده دیگر به این سازنده وابسته هستند. در خطوط 12-9 یک سازنده پیشفرض بدون پارامتر تعریف شده است. توجه کنید که از کلمه کلیدی this باید بعد از علامت کالن ( : ) استفاده کنید. این کلمه کلیدی به شما اجازه میدهد که یک سازنده دیگر موجود در داخل کلاس را فراخوانی کنید. مقادیر پیشفرضی به فیلدها از طریق سازنده پیشفرض اختصاص میدهیم.
چون ما سه آرگومان برای پرانتزهای بعد از کلمه کلیدی this سازنده پیشفرض در نظر گرفتهایم در نتیجه سازندهای که دارای سه پارامتر است فراخوانی شده و سه آرگومان به پارامترهای آن ارسال میشود. کدهای داخل بدنه چهارمین سازنده اجرا میشوند و مقادیر پارامترهای آن به هر یک از اعضای دادهای مربوط اختصاص داده میشود. نمیتوانیم هیچ کدی را در داخل بدنه اولین سازنده بنویسیم چون توسط سازنده چهارم اجرا میشوند. اگر کدی در داخل بدنه سازنده پیشفرض بنویسیم قبل از بقیه کدها اجرا میشود. دومین سازنده (خطوط 17-14) به یک آرگومان نیاز دارد که همان فیلد name کلاس Person است.
وقتی این پارامتر با یک مقدار رشتهای پر شد، سپس به پارامترهای سازنده چهارم ارسال شده و در کنار دو مقدار پیشفرض دیگر (0 برای age و 0 برای height) قرار میگیرد. پس در داخل بدنه دومین سازنده هم نباید کدی بنویسیم چون این کد نیز توسط سازنده چهارم اجرا میشود. در خط 22-91 سومین سازنده تعریف شده است که بسیار شبیه دومین سازنده است با این تفاوت که دو پارامتر دارد. مقدار دو پارامتر سومین سازنده به اضافهی یک مقدار پیشفرض صفر برای سومین آرگومان، به چهارمین سازنده با استفاده از کلمه کلیدی this ارسال میشود.
Person firstPerson = new Person(); Person secondPerson = new Person("Jack"); Person thirdPerson = new Person("Mike", 23); Person fourthPerson = new Person("Chris", 18, 152);
همانطور که مشاهده میکنید با ایجاد چندین سازنده برای یک کلاس، چندین راه برای ایجاد یک شیء بر اساس دادههایی که نیاز داریم به وجود میآید. در مثال بالا 4 نمونه از کلاس Person ایجاد کردهایم و چهار تغییر در سازنده آن به وجود آوردهایم. سپس مقادیر مربوط به فیلدهای هر نمونه را نمایش میدهیم. یکی از موراد استفاده از کلمه کلیدی this به صورت زیر است. فرض کنید نام پارامترهای متد کلاس شما یا سازنده، شبیه نام یکی از فیلدها باشد.
public Person(string name, int age, double height) { name = name; age = age; height = height; }
این نوع کدنویسی ابهام بر انگیز است و کامپایلر نمیتواند متغیر را تشخیص داده و مقداری به آن اختصاص دهد. اینجاست که از کلمه کلیدی this استفاده میکنیم.
public Person(string name, int age, double height) { this.name = name; this.age = age; this.height = height; }
قبل از هر فیلدی کلمه کلیدی this را مینویسیم و نشان میدهیم که این همان چیزی است که میخواهیم به آن مقداری اختصاص دهیم. کلمه کلیدی this ارجاع یک شیء به خودش را نشان میدهد.
فایده سازنده چیه؟ توی درسای قبل که مستقیما به فیلد های یک شی مقدار دهی می کردیم!