اثر پروانه ای

برنامه نویسی حرفه ای کامپیوتر به زبان سی شارپ - لیست کامل کلمات کلیدی در ʚĭɞ - ßữʈʨɾflỵ ⓔⓕⓕⓔⓒⓣ

مشخصات بلاگ
اثر پروانه ای

اثر پروانه‌ای نام پدیده‌ای است که به دلیل حساسیت سیستم‌های آشوب‌ناک به شرایط اولیه ایجاد می‌شود. این پدیده به این اشاره می‌کند که تغییری کوچک در یک سیستم آشوب‌ناک چون جو سیارهٔ زمین (مثلاً بال‌زدن پروانه) می‌تواند باعث تغییرات شدید (وقوع توفان در کشوری دیگر) در آینده شود.

ایده‌ٔ این‌که پروانه‌ای می‌تواند باعث تغییری آشوبی شود نخستین بار در ۱۹۵۲ در داستان کوتاهی به نام آوای تندر اثر ری بردبری مطرح شد. عبارت «اثر پروانه ای» هم در ۱۹۶۱ در پی مقاله‌ای از ادوارد لورنتس به وجود آمد. وی در صد و سی و نهمین اجلاس ای‌ای‌ای‌اس در سال ۱۹۷۲ مقاله‌ای با این عنوان ارائه داد که «آیا بال‌زدن پروانه‌ای در برزیل می‌تواند باعث ایجاد تندباد در تکزاس شود؟»

آخرین نظرات
  • ۱۱ بهمن ۹۵، ۱۷:۱۸ - فاروق کریمی زاده
    خوب بود.
اثر پروانه ای

۱۶ مطلب با کلمه‌ی کلیدی «event» ثبت شده است

بسم الله الرحمن الرحیم

سلام...

پیرو درخواست های مکرر برخی دوستان ، مبنی بر آموزش ساخت رابط کاربری برنامه "8 وزیر" در محیط گرافیکی #C ، تصمیم گرفتم این مطلب رو به همین موضوع اختصاص بدم. البته قطعا این مبحث زود هنگام در بلاگ قرار گرفت و امکان اینکه برای برخی از دوستان مبتدی ، درک این مفاهیم مشکل باشد، وجود دارد. قبلا از بقیه دوستان عذر خواهی می کنم.

ما در این درس قصد داریم برنامه ای بسازیم که در آن 64 شیء PictureBox وجود داشته باشد. هر کدام از این اشیاء دارای خصوصیات و رفتارهای مربوط به خود باشد (متمایز از بقیه اشیاء). اما قرار دادن 64 کنترل (شیئ) PictureBox روی فرم برنامه بصورت دستی و از طریق Toolbox ، کار طاقت فرسایی به نظر می‌رسد. بنابراین راهی جز تولید این 64 کنترل با استفاده از کدنویسی وجود ندارد.

در زبان برنامه نویسی #C دات نت ، با هر چیزی بصورت یک شیئ برخورد می شود. هرچیزی! هر شیئ دارای یک کلاس هست که قالب و طرح کلی آن شیئ را در خود دارد. برای مثال شیئ آچار دارای یک قالب ریخته‌گری است، که با ریختن مواد مذاب در داخل آن ، آچار بوجود می آید.

عبارت های لامبدا (Lambda Expressions)

سی شارپ 2.0 متدهای بی‌نام را معرفی کرد، که تا اینجا این گونه از متدها را بررسی کردیم. هرچند املاء متدهای بی‌نام تا حدودی طولانی بوده و نیاز به اطلاعاتی دارد که خود کامپایلر از آنها مطلع است. بجای اینکه مجبور باشید این اطلاعات تکراری را الحاق کنید، سی شارپ 3.0 عبارت های لامبدا را معرفی کرده که املاء و نگارش متدهای بی‌نام را کاهش داده است. شاید بخواهید بجای استفاده از متدهای بی‌نام از عبارت های لامبدا استفاده کنید. در حقیقت، اگر عبارت های لامبدا زودتر معرفی شده بودند، دیگر هرگز متدهای بی‌نام وجود نداشتند.

در نگارش متدهای بی‌نام، کلمه کلیدی delegate مازاد بر احتیاج است؛ به این علت که خود کامپایلر می بیند که شما درحال انتساب متد به delegate هستید. شما می توانید با انجام کارهای زیر، بسادگی، یک متد بی‌نام را به یک عبارت لامبدا تبدیل کنید:

  • کلیدواژه delegate را حذف کنید.
  • عملگر لامبدا ( <= ) را مابین لیست پارامترها و بدنه متد بی نام قرار دهید. عملگر لامبدا بصورت "می رود به" (goes to) خوانده می‌شود.

تکه کد زیر این تبدیل را نشان می دهد. خط اول یک متد بی نام را که به متغیر del انتساب داده شده را نشان می دهد. خط دوم همان متد بی نام را بعد از آنکه به عبارت لامبدا تبدیل شده را نشان می دهد که به متغیر le1 منتسب شده است.

متدهای بی‌نام

تا اینجا، شما دیده اید که می‌توانید از متدهای نمونه یا متدهای استاتیک برای نمونه سازی delegate استفاده کنید. در هرصورت، متد بخودی خود می‌تواند از قسمت های دیگر کد بصورت صریح فراخوانی شود و البته باید عضوی از یک کلاس یا ساختار باشد.

اگر متد تنها برای نمونه سازی delegate استفاده شده باشد چطور؟ در چنین شرایطی، بجز اینکه به نیازمندی های نحوی و املائی برای ساختن delegate احتیاج داریم، در واقع نیازی به ساختن یک متد با نام جداگانه وجود ندارد. متدهای بی نام به شما اجازه می‌دهند که از ساختن متدهای نامدار بیهوده جلوگیری کنید.

  • یک متد بی نام، متدی است که در محل نمونه سازی delegate ، اعلان می‌شود.

برای نمونه، شکل زیر دو نسخه از یک کلاس یکسان را نشان می‌دهد. نسخه سمت چپ یک متد به نام Add20 را اعلان و استفاده می‌کند. نسخه سمت راست بجای آن از متد بی نام استفاده می‌کند. قسمت هایی از کد که سایه گذاری نشده، کاملا برابر هستند.

احضار delegate هایی که دارای مقدار برگشتی هستند

اگر یک وکیل دارای مقدار بازگشتی باشد و در لیست احضارش بیش از یک متد موجود باشد، موارد زیر رخ خواهد داد:

  • مقداری که از آخرین متد موجود در لیست احضار برگشت داده می‌شود همان مقدار برگشتی وکیل است.
  • مقدار برگشتی همه متدهای دیگر نادیده گرفته می‌شود.

برای مثال کد زیر یک delegate اعلان می‌کند که دارای مقدار برگشتی از نوع int است. تابع Main یک شیئ از آن delegate ساخته، سپس 2 متد به آن اضافه می‌کند، بعد از آن delegate را در بیان WriteLine فراخوانی کرده و مقدار برگشتی آن را چاپ می‌کند. شکل زیر یک ارائه گرافیکی از کد را نشان می‌دهد.

حذف متدها از delegate

شما همچنین می توانید یک متد را با استفاده از عملگر =- از delegate حذف کنید. تکه کد زیر طرز استفاده از این عملگر را نشان می دهد. شکل زیر نتیجه اجرای کد را نشان می دهد.

delVar -= SCl.m3; // Remove the method from the delegate.

پس از حذف متد از delegate شکل بصورت زیر در می آید.

انتساب delegate ها

به این دلیل که delegate ها نوع های مرجع هستند، شما می توانید ارجاع گنجانده شده در یک  متغیر وکالتی را با انتساب یک ارجاع به آن متغیر وکالتی تغییر دهید. شیئ وکالتی قدیمی توسط زباله روب (Garbage Collector) عزل خواهد شد.

برای مثال، کد زیر مقدار delVar را تنظیم کرده سپس آنرا تغییر می دهد. شکل زیر این موضوع را نشان می دهد.

MyDel delVar;
delVar = myInstObj.MyM1; // Create and assign the delegate object.
...
delVar = SClass.OtherM2; // Create and assign the new delegate object.


اعلان نوع وکالتی (delegate)

همونطوری که در ابتدای بخش قبل گفتم، delegate ها "نوع" هستند، درست مثل کلاس ها که نوع هستند. و مشابه کلاس ها باید قبل از اینکه بتوانید از delegate ها استفاده کنید متغیرها و اشیاء از همان نوع را بسازید. مثال زیر طرز اعلان نوع وکالتی را نشان می دهد:

delegate void MyDel(int x);

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

در مثال قبل مشخص شده که شیئ وکالتی از نوع MyDel فقط متدهایی که دارای تنها یک پارامتر از نوع int بوده و نوع برگشتی ندارند را قبول می کند. شکل زیر در سمت چپ نوع وکالتی، و در سمت راست شیئ وکالتی را نشان می دهد.

نوع وکالتی

اعلان نوع وکالتی با اعلان متد، از دو جهت تفاوت دارد. اعلان نوع وکالتی

  • با کلمه کلیدی delegate شروع می شود
  • دارای بدنه متد نمی باشد

نکته

هرچند اعلان نوع وکالتی شبیه اعلان متد است، نیازی نیست که آنرا در داخل یک کلاس اعلان کنید، زیرا خودش "نوع" است.

delegate (وکیل) چیست؟
شما می توانید فکر کنید یک delegate یک شیئ است که یک یا چند متد را در خود نگهداری می کند. البته درحالت نرمال، اشیائ خاصیت اجرایی ندارند، اما یک delegate با اشیاء معمولی تفاوت دارد. شما می توانید یک delegate را اجرا کنید و هنگامی که شما چنین کاری انجام دهید، آن delegate تمام متد یا متدهایی را که در خود نگهداری می کند را اجرا خواهد کرد.
دراین فصل املاء (syntax) و معناشناسی ساخت و استفاده از delegate را توضیح خواهیم داد. در فصول آینده خواهیم دید که چگونه می توانیم با استفاده از delegate ها کدهای اجرایی را از یک متد به متد دیگر پاس دهیم و اینکه چرا اینکار سودمند است.

رابط (interface) می تواند یک رویداد را اعلان کند. مثال زیر چگونگی پیاده سازی رویدادهای رابطی را در یک کلاس نشان می دهد. بطور مقدماتی قواعد و قوانین کار مانند پیاده سازی متد ها یا پراپرتی های رابطی می باشد.
برای پیاده سازی رویدادهای رابطی در یک کلاس

  • رویداد را در کلاستان اعلان کرده، سپس آنرا در مکان دلخواه فراخوانی کنید.
    namespace ImplementInterfaceEvents
    {
        public interface IDrawingObject
        {
            event EventHandler ShapeChanged;
        }
        public class MyEventArgs : EventArgs 
        {
            // class members
        }
        public class Shape : IDrawingObject
        {
            public event EventHandler ShapeChanged;
            void ChangeShape()
            {
                // Do something here before the event…
    
                OnShapeChanged(new MyEventArgs(/*arguments*/));
    
                // or do something here after the event. 
            }
            protected virtual void OnShapeChanged(MyEventArgs e)
            {
                if(ShapeChanged != null)
                {
                   ShapeChanged(this, e);
                }
            }
        }
    
    }

مثال
مثال زیر نشان می دهد که چگونه موقعیتی تقریبا" غیر عادی را که در آن کلاس شما از دو رابط یا بیشتر ارث بری می کند و درعین حال هر رابط دارای یک رویداد با نام مشابه است را مدیریت کنید. در این موقعیت، شما باید حداقل برای یکی از رویدادها، بصورت صریح پیاده سازی رابط را فراهم کنید. وقتی شما برای یک رویداد، پیاده سازی صریح رابط می نویسید، همچنین باید دستیابی کننده های رویداد add و remove را بنویسید. در حالت عادی اینها توسط کامپایلر فراهم می شوند، اما در این مورد کامپایلر نمی تواند آنها را فراهم کند.

مثال ساده زیر راه استاندارد اعلان رویدادها در یک کلاس پایه ای را نشان می دهد، در نتیجه آنها می توانند از طریق کلاس های مشتق شده هم برپا شوند. این الگو بطور گسترده ای در کلاس های Windows Form در کتابخانه کلاس دات نت فریم وورک استفاده شده اند.
وقتی که شما یک کلاس می سازید که توانایی استفاده به عنوان کلاس پایه برای دیگر کلاس ها را دارد، می بایست به این حقیقت توجه داشته باشید که رویدادها نوعی خاص از وکیل ها هستند که فقط می توانند از داخل کلاسی که آنها را اعلان کرده فراخوانی شوند. کلاس های مشتق شده نمی توانند مستقیما" رویداد هایی که در داخل کلاس پایه تعریف شده است را فراخوانی کنند. هرچند در بعضی مواقع شما ممکن است رویدادی را بخواهید که فقط توانایی فراخوانی توسط کلاس پایه را داشته باشد، در اکثر مواقع، شما می بایست کلاس مشتق شده را قادر سازید که رویدادهای کلاس پایه را فراخوانی کند. برای انجام این کار، شما می توانید یک متد فراخواننده محافظت شده (protected) در کلاس پایه بسازید، بگونه ای که رویداد را دربر بگیرد.کلاس های مشتق شده می توانند با صدا زدن یا بازنویسی (override) کردن این متد فراخواننده، رویداد را بصورت غیر مستقیم فراخوانی نمایند.