PDA

View Full Version : مبتدی: مشکل در فهم Constructor



parsa lotfy
پنج شنبه 17 دی 1394, 22:00 عصر
سلام...
خیلی کوتاه فقط بگم ک من ی مبتدیم و دارم از روو کتاب دیتل C#‎‎ یاد میگیرم...
قسمتی از این کتاب چنین کدی رو نوشته ک من 3 روزه میخونم نمیفهمم !!!

این کد Class :

// Fig. 10.5: Time2.cs
// Time2 class declaration with overloaded constructors.
using System; // for class ArgumentOutOfRangeException

public class Time2
{
private int hour; // 0 - 23
private int minute; // 0 - 59
private int second; // 0 - 59




// constructor can be called with zero, one, two or three arguments
public Time2( int h = 0, int m = 0, int s = 0 )
{
SetTime( h, m, s ); // invoke SetTime to validate time
} // end Time2 three-argument constructor

// Time2 constructor: another Time2 object supplied as an argument
public Time2( Time2 time )
: this( time.Hour, time.Minute, time.Second ) { }

// set a new time value using universal time; ensure that
// the data remains consistent by setting invalid values to zero
public void SetTime( int h, int m, int s )
{
Hour = h; // set the Hour property
Minute = m; // set the Minute property
Second = s; // set the Second property
} // end method SetTime






// property that gets and sets the hour
public int Hour
{
get
{
return hour;
} // end get
set
{
if ( value >= 0 && value < 24 )
hour = value;
else
throw new ArgumentOutOfRangeException(
"Hour", value, "Hour must be 0-23" );
} // end set
} // end property Hour

// property that gets and sets the minute
public int Minute
{
get
{
return minute;
} // end get
set
{
if ( value >= 0 && value < 60 )
minute = value;
else
throw new ArgumentOutOfRangeException(
"Minute", value, "Minute must be 0-59" );
} // end set
} // end property Minute

// property that gets and sets the second
public int Second
{
get
{
return second;
} // end get
set
{
if ( value >= 0 && value < 60 )
second = value;
else
throw new ArgumentOutOfRangeException(
"Second", value, "Second must be 0-59" );
} // end set
} // end property Second






// convert to string in universal-time format (HH:MM:SS)
public string ToUniversalString()
{
return string.Format(
"{0:D2}:{1:D2}:{2:D2}", Hour, Minute, Second );
} // end method ToUniversalString

// convert to string in standard-time format (H:MM:SS AM or PM)
public override string ToString()
{
return string.Format( "{0}:{1:D2}:{2:D2} {3}",
( ( Hour == 0 || Hour == 12 ) ? 12 : Hour % 12 ),
Minute, Second, ( Hour < 12 ? "AM" : "PM" ) );
} // end method ToString




} // end class Time2



اینم کد Main :

// Fig. 10.6: Time2Test.cs
// Overloaded constructors used to initialize Time2 objects.
using System;

public class Time2Test
{
public static void Main( string[] args )
{
Time2 t1 = new Time2(); // 00:00:00
Time2 t2 = new Time2( 2 ); // 02:00:00
Time2 t3 = new Time2( 21, 34 ); // 21:34:00


Time2 t4 = new Time2( 12, 25, 42 ); // 12:25:42
Time2 t5 = new Time2( t4 ); // 12:25:42


Time2 t6; // initialized later in the program

Console.WriteLine( "Constructed with:\n" );
Console.WriteLine( "t1: all arguments defaulted" );
Console.WriteLine( " {0}", t1.ToUniversalString() ); // 00:00:00
Console.WriteLine( " {0}\n", t1.ToString() ); // 12:00:00 AM

Console.WriteLine(
"t2: hour specified; minute and second defaulted" );
Console.WriteLine( " {0}", t2.ToUniversalString() ); // 02:00:00
Console.WriteLine( " {0}\n", t2.ToString() ); // 2:00:00 AM

Console.WriteLine(
"t3: hour and minute specified; second defaulted" );
Console.WriteLine( " {0}", t3.ToUniversalString() ); // 21:34:00
Console.WriteLine( " {0}\n", t3.ToString() ); // 9:34:00 PM

Console.WriteLine( "t4: hour, minute and second specified" );
Console.WriteLine( " {0}", t4.ToUniversalString() ); // 12:25:42
Console.WriteLine( " {0}\n", t4.ToString() ); // 12:25:42 PM

Console.WriteLine( "t5: Time2 object t4 specified" );
Console.WriteLine( " {0}", t5.ToUniversalString() ); // 12:25:42
Console.WriteLine( " {0}", t5.ToString() ); // 12:25:42 PM

// attempt to initialize t6 with invalid values
try
{
t6 = new Time2( 27, 74, 99 ); // invalid values
} // end try
catch ( ArgumentOutOfRangeException ex )
{
Console.WriteLine( "\nException while initializing t6:" );
Console.WriteLine( ex.Message );
} // end catch

Console.ReadKey();

} // end Main
} // end class Time2Test


کد کلاس رو نیگا کنین... 2 تا Constructor داره ...
Constructor اولیو کاملا فهمیدم و با طرز کارش اشنا هستم...

اما از دومی سر در نمیارم متاسفانه ...
// Time2 constructor: another Time2 object supplied as an argument
public Time2( Time2 time )
: this( time.Hour, time.Minute, time.Second ) { }
میدونین یا ی ساختار دیگه ای نوشته شده ، مثلا سازنده ی اولی خیلی ساده ارگومان هارو داخل پرانتز نوشته و کاری ک باید انجام بشه رو تووی کروشه قرار داده...اما دومی چی ؟!
ی جور دیگه ای نوشته شده ... از this استفاده کرده ، از کولن (:) استفاده کرده ، ارگومان های داخل پرانتز چی هستن ؟ تووی کروشه ی اخرش چرا هیچی ننوشته ؟کاری ک سازنده باید انجام بده کجاش قرار داده شده ؟؟؟

عاقا کلا با سازنده دومی مشکل دارم هیچیشو نمیفهمم !!!!!!!:گریه::گریه::گریه:

لطفا توضیج بدین خیلی وقتمو گرفت این تیکه کد ...
با تشکر:قلب::قلب::قلب:

c0mmander
جمعه 18 دی 1394, 01:38 صبح
کلمه کلیدی this در سی شارپ یا برای اشاره به اعضای کلاست هست و یا برای فوروارد کردن انواع متد ها یا سازنده ها.

شما در ابتدای کلاس یک سازنده 3 پارامتری رو تعریف کرده اید. با استفاده از دستور دوم دقیقا اشاره میکنید یک نمونه از کلاس شما رو به عنوان پارامتر دریافت میکنه.
مقدار این کلاس که شامل 3 خاصیت time.Hour, time.Minute, time.Second هستند توسط سازنده قبلی مقدار دهی میشه.

به عبارت دیگه. با اشاره کردن به سازنده ای که دارای سه آرگومان هست همان دستورات در نظر گرفته میشه.

در سازنده دوم کلاس time2 به عنوان آرگان ورودی سازنده در نظر گرفته شده. سه خاصیت Hour و Minute و Second که هر سه نوع یک یکسانی با سازنده اول دارند تعریف شده.

در کلاس اصلی برنامه یک بار یک نمونه از کلاس time2 با مقادیری تعریف شده


Time2 t4 = new Time2( 12, 25, 42 ); // 12:25:42

حالا با استفاده میتوان با استفاده از سازنده دوم کلاس time2 میشه یک نمونه ای ای از قبل ساخته رو بدون وارد کرد مجدد هر سه سازنده, مجددا تعریف کرد.
یعنی سازنده دوم یک شی از نوع کلاس time2 رو دریافت میکنید. با استفاده از کلمه کلیدی this مقادیر این کلاس که شامل time.Hour, time.Minute, time.Second هستند به سازنده ای که دارای 3 پارامتر هست پاس میده و دستورات سازنده اول رو اجرا میکند.

چیزی که لازمه بدونی اینکه
1- زمانی از این حالت استفاده میشه که دستورات سازنده در تمامی سازنده ها مشترک باشه.
2- در صورتی که نیاز داشته باشی یک مقدار مستقیما به سازنده اصلی بدی حتما نیاز نیست که یک کلاس تعریف کنی. یعنی بصورت زیر هم میتونی از تکنیک استفاده از this داخل سازنده استفاده کنی:


public Time2( int h)

: this( h, (int)10, (int)10 ) { }


دلیل استفاده از این کار همون طور که خودت هم متوجه شدی:
1- جلوگیری از تکرار کد های نوشته شده در سازنده ها در این حالت هاست
2- برای ساخت یک کلاس مشابه کلاس موجود.یا ساخت یک کلاس با استفاده از مقادیر موجود. دقت کن که واژه مشابه به معنی کپی نیست!

ویرایش:
لینک های مفیدی که داخل انجمن پیدا کردم:

http://barnamenevis.org/showthread.php?420006-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%B4%DB%8C-%DA%AF%D8%B1%D8%A7-%D8%AF%D8%B1-%D8%B3%DB%8C-%D8%B4%D8%A7%D8%B1%D9%BE&p=1878948&viewfull=1#post1878948

اینها هم برای کلمه کلیدی base هست که شاید بعدا با آنها مواجه بشی:

http://barnamenevis.org/showthread.php?395205-%D9%85%D9%81%D9%87%D9%88%D9%85-base-%D8%AF%D8%B1-object-orinted&highlight=%DA%A9%D9%84%D9%85%D9%87+%DA%A9%D9%84%DB %8C%D8%AF%DB%8C+base

http://barnamenevis.org/showthread.php?420006-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%B4%DB%8C-%DA%AF%D8%B1%D8%A7-%D8%AF%D8%B1-%D8%B3%DB%8C-%D8%B4%D8%A7%D8%B1%D9%BE&p=1878957&viewfull=1#post1878957

parsa lotfy
جمعه 18 دی 1394, 09:52 صبح
واقعا بابت اینکه وقت گذاشتید و این مطلبو نوشتید متشکرم ....

فقط ی ایراد دارم :


. با استفاده از کلمه کلیدی this مقادیر این کلاس که شامل time.Hour, time.Minute, time.Second هستند به سازنده ای که دارای 3 پارامتر هست پاس میده و دستورات سازنده اول رو اجرا میکند.

چرا اینجوری کار میکنه ؟!

ینی من نمیفهمم که چرا ()this : چنین عملکردیو داره :متفکر:

c0mmander
جمعه 18 دی 1394, 10:44 صبح
واقعا بابت اینکه وقت گذاشتید و این مطلبو نوشتید متشکرم ....

فقط ی ایراد دارم :



چرا اینجوری کار میکنه ؟!

ینی من نمیفهمم که چرا ()this : چنین عملکردیو داره :متفکر:

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

همون طور که گفتم کلمه کلیدی this دو کار رو انجام میده. یکی از وظایفش اشاره کردن به سازنده یا متد هست.
بلوک زیر رو در مثالت ببین:



// constructor can be called with zero, one, two or three arguments

public Time2( int h = 0, int m = 0, int s = 0 )

{

SetTime( h, m, s ); // invoke SetTime to validate time

} // end Time2 three-argument constructor



// Time2 constructor: another Time2 object supplied as an argument

public Time2( Time2 time )

: this( time.Hour, time.Minute, time.Second ) { }





سازنده اول h,m,s با مقدار پیشفرض صفر برای هرکدوم از اونها در نظر گرفته شده.
با حالا در سازنده دوم (همون طور که میدونی یک کلاس میتونه چندین سازنده داشته باشه) با استفاده از :this به یکی از سازنده های موجود کلاس اشاره میکنه و مقادیر خودش رو به اون پاس میده.مثلا در اینجا تنها یک سازنده 3 پارامتری هست. پس


: this( time.Hour, time.Minute, time.Second ) { }

هم باید 3 پارامتر با امضای همون سازنده رو داشته باشه همون طور که خودت هم دیدی هر سه امضا درسته و از نوع int هست.

حالا کامپایلر متوجه میشه که باید این سازنده مقادیر اون به چه سازنده ای پاس بشه.
در اینجا اگر فقط نوشته بشه:


: this( time.Minute, time.Second ) { }

اشتباه ست.
حتما باید سه پارامتر عددی در این مثال وجود داشته باشه. حالا اگر این سازنده بصورت زیر تعریف شده باشه چی:


public Time2( int h)

: this( h, 0, 0 ) { }



که در این حالت درست هست و مقادیر به سازنده اول پاس داده میشه و دستورات سازنده اول اجرا میشه.

این یکی از کاربرد های this هست . این حالت حتی برای متد هم قابل استفاده ست.

ژیار رحیمی
جمعه 18 دی 1394, 11:11 صبح
دوست گرامی شما برای درک بهتر چندریختی(polymorphism) در OOP رو مطالعه کن
http://www.tutorialspoint.com/csharp/csharp_polymorphism.htm
https://msdn.microsoft.com/en-us/library/ms173152.aspx

areeef
جمعه 18 دی 1394, 11:14 صبح
دوست عزیز c0mmander اگر نخوایم از this استفاده کنیم شکل دیگه دستورش به چه شکل میشه ؟

c0mmander
جمعه 18 دی 1394, 12:28 عصر
دوست عزیز c0mmander اگر نخوایم از this استفاده کنیم شکل دیگه دستورش به چه شکل میشه ؟

اگر نخواهیم از this استفاده کنیم بجای کد زیر:


public Time2( Time2 time )
: this( time.Hour, time.Minute, time.Second ) { }




باید بصورت این تغییر داد:



// Time2 constructor: another Time2 object supplied as an argument
public Time2( Time2 time )
{
SetTime(time.Hour, time.Minute, time.Second ); // invoke SetTime to validate time
}

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