در قسمت قبل با چکونگي ارسال argument از طريق reference و همچنين با کلمات کليدي out، ref و params آشنا شديد. در اين قسمت قصد داريم با return کردن object از متد، Method Overloading و overload کردن constructor آشنا شويم.
Return کردن object از متد
تا اينجا type هاي مختلفي را از يک متد return ميکرديم البته در سيشارپ طراحی وب سایت شما ميتوانيد هر data type اي را از يک متد return کنيد مثل int، double، float و… اما در اينجا قصد داريم چيز ديگري را از متد بازگردانيم: class types.
در برنامهي زير کلاسي به اسم Person وجود دارد که در اين کلاس متدي به اسم ()CreateNewPerson است که يک شيء از جنس Person ميسازد و اين شيء را return ميکند:
using System;
class ReturnObExample
{
static void Main()
{
Person firstPerson = new Person("Catherine", "Gilbert");
Console.Write("Fist Person = ");
firstPerson.Show();
Person secondPerson = firstPerson.CreateNewPerson("Damon", "Salvatore");
Console.Write("Second Person = ");
secondPerson.Show();
}
}
class Person
{
string Name, Family;
public Person(string name, string family)
{
Name = name;
Family = family;
}
public Person CreateNewPerson(string name, string family)
{
Person ob = new Person(name, family);
ob.Name = name;
ob.Family = family;
return ob;
}
public void Show()
{
Console.WriteLine("Name: {0}, Family: {1}", Name, Family);
}
}
همانطور که ميبينيد secondPerson را توسط متد ()CreateNewPerson از شيء firstPerson بهوجود آورديم. در اين متد يک شيء از جنس Person ساخته شده و نام و نامخانوادگي (از طريق پارامتر) به فيلدهاي اين شيء اختصاص مييابد و سپس reference اين شيء return ميشود. در متد ()Main متد ()CreateNewPerson از شيء firstPerson فراخواني شده و شيء جديدي که بهوجود آورده است را به secondPerson متصل ميکند. به اين ترتيب يک شيء از جنس Person ساخته و به secondPerson reference متصل شد که داراي فيلدهاي نام و نامخانوادگي مخصوص به خودش است.
Return کردن يک آرايه
از آنجا که آرايهها در سيشارپ object هستند، يک متد همچنين ميتواند يک آرايه را نيز return کند. براي مثال به برنامهي بالا يک متد ديگر به اسم ()CreateFriends اضافه کرديم که در آرايهاي از جنس string يک سري اسم (اسامي دوستان) را ذخيره ميکند و در نهايت توسط متد ()GetFriends اين آرايه را return ميکنيم:
using System;
class ReturnObExample
{
static void Main()
{
Person firstPerson = new Person("Catherine", "Gilbert");
Console.Write("Fist Person = ");
firstPerson.Show();
Person secondPerson = firstPerson.CreateNewPerson("Damon", "Salvatore");
Console.Write("Second Person = ");
secondPerson.Show();
Console.WriteLine();
firstPerson.CreatFriends("Stefan", "Damon", "Elena");
string[] personFriends = firstPerson.GetFriends();
Console.Write("Catherine's Friends: ");
for (int i = 0; i < personFriends.Length; i++)
{
Console.Write(personFriends[i] + ", ");
}
Console.WriteLine();
}
}
class Person
{
string Name, Family;
string[] Friends;
public string[] GetFriends()
{
return Friends;
}
public Person(string name, string family)
{
Name = name;
Family = family;
}
public Person CreateNewPerson(string name, string family)
{
Person ob = new Person(name, family);
ob.Name = name;
ob.Family = family;
return ob;
}
public void Show()
{
Console.WriteLine("Name: {0}, Family: {1}", Name, Family);
}
public void CreatFriends(params string[] buddies)
{
Friends = new string[buddies.Length];
for (int i = 0; i < buddies.Length; i++)
Friends[i] = buddies[i];
}
}
توجه کنيد که متد ()GetFriends چگونه آرايهاي از جنس string را بازميگرداند. شما ميتوانيد آرايهاي با ابعاد بيشتر را نيز return کنيد.
Method Overloading
در سيشارپ دو يا بيشتر از دو متد ميتوانند نام يکساني داشته باشند، بهشرطي که تعريف پارامترهاي آنها متفاوت باشد. در اينجور موارد گفته ميشود که متدها overload شدهاند و درکل به اين پروسه method overloading گفته ميشود. Method overloading يکي از جنبههاي اجراي polymorphism (چند ريختي) است.
1class Program
{
static void Main()
{
MethodA();
MethodA("");
}
static void MethodA()
{
}
static void MethodA(string a)
{
}
}
همانطور که ميبينيد در مثال بالا دو متد همنام به اسم ()MethodA داريم که يکي بدون پارامتر است و ديگري يک پارامتر از جنس string دارد. درکل براي overload کردن يک متد کافي است که ورژنهاي مختلفي از آن متد را تعريف کنيد. براي اين کار بايد يک محدوديت را در هنگام overload کردن رعايت کنيد: نوع يا تعداد پارامترهاي هر متد overload شده بايد با بقيه متفاوت باشد. همچنين کافي نيست که فقط return-type يک متد overload شده با ديگري متفاوت باشد بلکه نوع يا تعداد پارامترهاي استفاده شده در آن بايد با بقيه متدهاي overload شده فرق کند.
به مثال زير توجه کنيد:
using System;
class MethodOverloading
{
public int Addition(int a, int b)
{
return a + b;
}
public int Addition(int a, int b, int c)
{
return a + b + c;
}
public float Addition(float a, float b)
{
return a + b;
}
public float Addition(float a, float b, float c)
{
return a + b + c;
}
}
//Now you can use those Addition method four types
class hub
{
public static void Main()
{
MethodOverloading methOverload = new MethodOverloading();
Console.WriteLine("Addition of two integers: "
+ methOverload.Addition(2, 5));
Console.WriteLine("Addition of two double type values: "
+ methOverload.Addition(0.40f, 0.50f));
Console.WriteLine("Addition of three integers: "
+ methOverload.Addition(2, 5, 5));
Console.WriteLine("Addition of three double type values: "
+ methOverload.Addition(0.40f, 0.50f, 0.60f));
}
}
در مثال بالا ما چندين ورژن از متد ()Addition را داريم که هر کدام از نظر نوع و تعداد پارامترهاي استفاده شده در آنها با بقيه متفاوت هستند و همچنين return-type آنها هم ميتواند متفاوت باشد. توجه کنيد که overload کردن به شکل زير کاملاً نادرست است:
// One OvlDemo(int) is OK.
public void OvlDemo(int a)
{
Console.WriteLine("One parameter: " + a);
}
/* Error! Two OvlDemo(int)s are not OK even though
return types differ. */
public int OvlDemo(int a)
{
Console.WriteLine(“One parameter: “ + a);
return a * a;
}
توجه به اين نکته ضروري است که overload کردن ربطي به return-type ندارد و تنها پارامترها و جنس پارامترها اهميت دارند. در مثال بالا با توجه به اينکه return-type متفاوت است اما بهدليل يکي بودن پارامترها overload اتفاق نميافتد و برنامه کامپايل نميشود. در ويژوال استوديو هنگاميکه يک متد را صدا ميزنيد که چندين overload دارد با چنين چيزي مواجه ميشويد:
در اينجا IntelliSense ويژوال استوديو به شما نشان ميدهد که اين متد چهار overload دارد و شما ميتوانيد مقادير مختلفي را بهعنوان argument به اين متد بدهيد. کافي است که کليدهاي بالا و پايين را فشار دهيد تا overload هاي اين متد را مشاهده کنيد.
همانطور که ذکر شد، method overloading يکي از جنبههاي اجراي polymorphism است و باعث اجراي الگوي “one interface, multiple methods” ميشود. مثلاً در زباني مثل C که method overloading را ساپورت نميکند هر متد بايد يک اسم منحصربهفرد داشته باشد درحاليکه شما مکرراً نياز داريد تا توسط يک متد روي data type هاي مختلف کاري را انجام دهيد. همان برنامه بالا که از متد ()Addition استفاده شده بود را در نظر بگيريد. اگر قرار بود اينکار را توسط زبان C انجام دهيم ميبايست چهار function مختلف با اسمهاي مختلف تعريف ميکرديم درحاليکه اين چهار function همهگي يک کار يکسان را انجام ميدهند. مسلماً اينکار اندکي قضيه را پيچيدهتر ميکند زيرا با توجه به اينکه همهي اين function ها يک کار را انجام ميدهند و مفهوم يکساني دارند شما مجبوريد ? اسم مختلف را بهخاطر بسپاريد. مثلاً متد ()WriteLine از کلاس Console نوزده overload دارد. تصور کنيد در اين موارد که تعداد overload ها زياد است آنگاه تعريف کردن متدهاي جداگانه با اسامي مجزا عملاً کار احمقانهاي است.
Overload Constructors
Constructor ها نيز ميتوانند همانند متدها overload شوند. اينکار باعث ميشود بتوانيد به طرق مختلفي object هاي خود را بسازيد. به مثال زير توجه کنيد:
44
// Demonstrate an overloaded constructor.
using System;
class MyClass
{
public int x;
public MyClass()
{
Console.WriteLine("Inside MyClass().");
x = 0;
}
public MyClass(int i)
{
Console.WriteLine("Inside MyClass(int).");
x = i;
}
public MyClass(double d)
{
Console.WriteLine("Inside MyClass(double).");
x = (int)d;
}
public MyClass(int i, int j)
{
Console.WriteLine("Inside MyClass(int, int).");
x = i * j;
}
}
class OverloadConsDemo
{
static void Main()
{
MyClass t1 = new MyClass();
MyClass t2 = new MyClass(88);
MyClass t3 = new MyClass(17.23);
MyClass t4 = new MyClass(2, 4);
Console.WriteLine("t1.x: " + t1.x);
Console.WriteLine("t2.x: " + t2.x);
Console.WriteLine("t3.x: " + t3.x);
Console.WriteLine("t4.x: " + t4.x);
}
}
خروجي:
در اينجا ()MyClass چهار overload دارد که هر کدام باعث ميشوند object به شکل متفاوتي ساخته شود. توسط کلمهکليدي new و argument هايي که براي ساخت شيء بهکار ميبريد، constructor مربوط به آن فراخواني ميشود و شيء را بهوجود ميآورد. با overload کردن constructor هاي کلاس، شما اين امکان را بهوجود ميآوريد که object ها به طرق مختلفي بتوانند ساخته شوند.
using System;
class Employee
{
public int IdNumber;
public double Salary;
public Employee()
{
IdNumber = 999;
Salary = 0;
}
public Employee(int empId)
{
IdNumber = empId;
Salary = 0;
}
public Employee(int empId, double sal)
{
IdNumber = empId;
Salary = sal;
}
public Employee(char code)
{
IdNumber = 111;
Salary = 100000;
}
}
public class CreateSomeEmployees
{
public static void Main()
{
Employee aWorker = new Employee();
Employee anotherWorker = new Employee(234);
Employee theBoss = new Employee('A');
Console.WriteLine("{0} --- {1}", aWorker.IdNumber,
aWorker.Salary);
Console.WriteLine("{0} --- {1}", anotherWorker.IdNumber,
anotherWorker.Salary);
Console.WriteLine("{0} --- {1}", theBoss.IdNumber,
theBoss.Salary);
}
}
در اين برنامه چهار overload از ()Employee وجود دارد که هرکدام بهنحوي باعث ساخت شيء ميشوند.
درخواست يک overloaded constructor از طريق this
هنگاميکه با constructor هاي overload شده کار ميکنيد، يک constructor ميتواند، constructor ديگري را درخواست کند. اينکار از طريق کلمهکليدي this انجام ميشود و فرم کلي آن بهشکل زير است:
1
2
3
constructor-name(parameter-list1) : this(parameter-list2) {
// ... body of constructor, which may be empty
}
در اينجا ابتدا با توجه به parameter-list2 يکي از constructor هاي overload شده اجرا ميشود و سپس اگر کدي درون constructor اصلي (constructor اوليه) وجود داشته باشد، اجرا ميشود.
// Demonstrate invoking a constructor through this.
using System;
class AlphaBeta
{
public int Alpha, Beta;
public AlphaBeta() : this(0, 0)
{
Console.WriteLine("Inside AlphaBeta()");
}
public AlphaBeta(AlphaBeta obj) : this(obj.Alpha, obj.Beta)
{
Console.WriteLine("Inside AlphaBeta(obj)");
}
public AlphaBeta(int i, int j)
{
Console.WriteLine("Inside AlphaBeta(int, int)");
Alpha = i;
Beta = j;
}
}
class OverloadConsDemo
{
static void Main()
{
AlphaBeta ob1 = new AlphaBeta();
AlphaBeta ob2 = new AlphaBeta(8, 9);
AlphaBeta ob3 = new AlphaBeta(ob2);
Console.WriteLine();
Console.WriteLine("ob1.x, ob1.y: " + ob1.Alpha + ", " + ob1.Beta);
Console.WriteLine("ob2.x, ob2.y: " + ob2.Alpha + ", " + ob2.Beta);
Console.WriteLine("ob3.x, ob3.y: " + ob3.Alpha + ", " + ob3.Beta);
}
}
خروجي:
به اين نکته توجه کنيد، پارامترهايي که بعد از this ميآيند مشخص ميکنند که کدامين constructor بايد در ابتدا اجرا شود. مثلاً براي ()AlphaBeta که خودش پارامتري ندارد، (this(0, 0 دو عدد integer دارد و مشخص ميکند که ابتدا بايد آن constructor اي اجرا شود که دو پارامتر int دارد. بنابراين ابتدا محتويات (AlphaBeta(int i, int j اجرا شده و سپس محتويات ()AlphaBeta اجرا ميشود. در مورد (AlphaBeta(AlphaBeta obj نيز مراحل بهترتيب قبل است. (This(obj.Alpha, obj.Beta دو عدد int گرفته است بنابراين طراحی وب سایت ابتدا محتويات (AlphaBeta(int i, int j اجرا شده و سپس محتويات (AlphaBeta(AlphaBeta obj اجرا ميشود. يکي از مزاياي اين کار اين است که از کدنويسي اضافي جلوگيري ميکند. با اينکار شما ديگر در هر constructor نياز نداريد که براي مقداردهي به Alpha و Beta کد تکراري بنويسيد.
به مثال ديگري در اين زمينه توجه کنيد:
using System;
class Mouse
{
public Mouse()
: this(-1, "")
{
// Uses constructor initializer.
}
public Mouse(int weight, string name)
{
// Constructor implementation.
Console.WriteLine("Constructor weight = {0}, name = {1}",
weight,
name);
}
}
class Program
{
static void Main()
{
// Test the two constructors for Mouse type.
Mouse mouse1 = new Mouse();
Mouse mouse2 = new Mouse(10, "Sam");
}
}
تمرين شماره ??: در اين تمرين ميبايست يک جعبهي موسيقي درست کنيد. اين جعبه موسيقي، بايد چندين هنرمند داشته باشد و هر هنرمند ميتواند چندين آلبوم و تک آهنگ داشته باشد. همچنين ميبايست قابليت Play و Stop کردن را به اين جعبه موسيقي بدهيد و بتوانيد آلبومها و آهنگها را حذف و اضافه کنيد.
راهنمايي:
using System;
using System.Media;
class MyClass
{
static void Main()
{
SoundPlayer myPlayer = new SoundPlayer(@"c:\mywavfile.wav");
myPlayer.Play();
myPlayer.Stop();
}
}
اين تمرين را تا آنجا که ميتوانيد شيگرا بنويسيد. در قسمت بعد حل تمرين روي سايت قرار ميگيرد.
توجه: زين پس هر يک از دوستان که جواب تمرينهاي زنگ سيشارپ را براي ما ايميل کند، به عنوان تشويقي يک نکتهي سيشارپ بهصورت شخصي براي وي فرستاده ميشود.
DOWNLOAD PDF