Dart Const (classes - static const)

Flutter Challenge(چالش فلاتر)

قسمت قبلی : بررسی مفاهیم اولیه و معرفی const variables.

? توی قسمت قبلی در مورد const variables توضیح دادیم و فهمیدیم که در زمان کامپایل چه بلایی سر این نوع متغیر ها میاد.

? توی این قسمت که اولین قسمت از بررسی مفهوم const در کلاس ها هست به بررسی static const میپردازیم.

خب یکی از جملات مهمی رو که توی مقاله قبلی از داکیومنت با هم خوندیم رو دوباره مرور میکنیم.

If the const variable is at the class level, mark it static const.
اگر میخواهید یک متغیر const در سطح کلاس داشته باشید اون رو static کنید (static const ).

???خب وقتشه که نفوذ کنیم به اعماق این جمله و زیر و بمشو بریزیم بیرون.???


قبل از این وقتی که میخواستیم خارج از سطح کلاس یک متغیر رو const کنیم خیلی راحت این کار رو انجام میدادیم , ولی طبق جمله ای که اینجا گفته و تجربه ای که حتمن دارید وقتی بخوایم داخل یک کلاس یه متغیر رو const کنیم به ارور میخوریم و بهمون میگه که حتمن باید متغیر مورد نظر رو static هم کنی(static const).

پس طبق توضیحاتی که دادیم کد بالا غلطه و اگه امتحان کنید بهتون میگه که یا متغیر رو final کنید و یا static.

یعنی به شکل بالا.

❓تا حالا به این فکر کردید که که چرا؟

❓چرا اگه در سطح یه کلاس بخوایم یه const تعریف کنیم حتمن باید static باشه؟

❓یا اینکه فقط حفظ کردین و استفاده کردین؟

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

برای جواب به این سوال اول یه یادآوری از قسمت قبلی میکنیم, توی قسمت قبلی گفتیم که وقتی که یه متغیر رو (خارج از سطح کلاس ) const تعریف میکنیم اون متغیر در زمان کامپایل توسط کامپایلر رصد میشه و مقدار میگیره.

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

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

به صورت ساده هر کلاس شامل یک سری property و یک سری method هست که روی اون property ها عمل میکنن.

مثلن اینجا name و age همون property ها هستن و printName هم متد هستش.(از اینجا به بعد به property میگیم instance field - دلیل این نام گذاری هم اینجوری در نظر بگیرید که فقط در صورتی به property های یه کلاس دسترسی داریم که از اون کلاس نمونه یا instance بسازیم.)

برای دسترسی به این instance field و method ها باید از کلاسمون نمونه بسازیم.

User user = User('Arash' , 12);
user.printName();

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

User.CLASS_NAME;

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

گفتیم که instance field ها و method های یه کلاس بعد از اینکه از اون کلاس نمونه میسازیم قابل استفاده هستن و در واقع بعد از نمونه سازی مقدار میگیرن و وارد میدون میشن و قبل نمونه سازی نمیتونیم ازشون استفاده کنیم.

⁉️نمونه سازی چه زمانی انجام میشه؟ compile-time یا run-time؟

آفرین , توی run-time . پس این قسمت ها یعنی instance field ها و متد ها توسط کامپایلر رصد نمیشن(یا قابلیت این رو ندارن که در زمان کامپایل مقدار بگیرن چون که توی run-time نمونه ساخته میشه و این ها مقدار میگیرن) (منظور از رصد نشدن این نیست که کلن هیچ کاری روشون انجام نده , منظورمون اینجا اینه که مثل const ها باهاشون برخورد نمیکنه که همون لحظه کامپایل تجزیه و تحلیلشون کنه و بهشون مقدار بده.)

اگه هنوز توجیه نشدی که چرا نمونه سازی توی run-time انجام میشه!!! خب وقتی مثلن مینویسیم:

User user = new User('Arash' , 7);

این عملیات new کردن و ساختن نمونه توی run-time و وقتی که اجرای کد به اون قسمت رسید انجام میشه. و ممکنه توی حالت اجرا , کد ما چند بار بره و برگرده و دوباره برسه به این نقطه و هر بار که رسید به این نقطه دوباره یه نمونه جدید ساخته میشه.

مثلن این کد توی صفحه دوم از اپ فلاترمون هست و ما هی صفحه رو push میکنیم و این کد اجرا میشه و دوباره pop میکنیم. هر بار که این کد اجرا میشه یه نمونه جدید ساخته میشه.

پس فهمیدید چرا توی run-time اتفاق میوفته.

پس وقتی که نمونه سازی توی run-time انجام میشه و از طرفی هم instance field ها در سطح نمونه های ساخته شده از یک کلاس قابل دسترسی هستن پس این instance field ها در زمان کامپایل قابل مقدار دهی نیستن.

???نوع دیگه ای از نمونه سازی توی دارت داریم که به جای new از const استفاده میکنیم که باعث میشه قضیه یکم فرق کنه که اون رو توی مقاله بعدی یاد میگیریم.

⁉️فیلد هایی که به صورت static تعریف شدن چی؟

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

پس الان میتونی به اون سوال جواب بدی ؟ چرا اگه بخوایم یه فیلد رو داخل کلاس const کنیم حتمن باید static هم بشه؟

فکر...فکر...فکر..

جواب: همون طور که قبلن گفتیم وقتی یه چیزی const هست همون لحظه کامپایل توسط کامپایلر تجزیه میشه , خب instance filed های یک کلاس هم که بعد از نمونه سازی و در run-time مقدار میگیرن و قابلیت این رو ندارن که در زمان کامپایل مقدار بگیرن , از طرفی توی کلاس ها دو نوع فیلد که بیشتر نداریم (یا instance filed هستن و یا static) , پس اگه یه فیلدی بخواد const باشه چاره ای نداره جز اینکه static هم باشه که زمان کامپایل مقدار بگیره و از همون اول اول و نه وقتی که از کلاس نمونه میسازیم قابل استفاده باشه.


پس یه جمع بندی داشته باشیم.

  • هر کلاس تشکیل شده از یک سری property یا instance filed و method هایی که رو اون ها عمل میکنند . هم چنین هر کلاس میتونه فیلد هایی از نوع static داشته باشه.
  • توی هر کلاس فقط و فقط دو نوع فیلد میتونیم داشته باشیم. یا instance filed و یا static.
  • نوع اول یعنی instance filed ها در سطح نمونه های ساخته شده از کلاس قابل دسترسی هستن و تا از کلاس نمونه نسازیم نمیتونیم بهشون دسترسی داشته باشیم. پس در زمان کامپایل قابل رصد و مقدار دهی نیستن.(چون نمونه سازی یا new کردن در run-time انجام میشه.)
  • نوع دوم یعنی static در سطح خود کلاس تعریف و قابل دسترسیه و ربطی به نمونه های ساخته شده از کلاس نداره. پس این قابلیت رو دارن که در زمان کامپایل قابل رصد و مقدار دهی باشن.(توجه کنید که فقط قابلیت این موضوع رو دارن و باید حتمن با const ترکیب بشن که این قابلیت بالقوه به بالفعل تبدیل بشه)
  • وقتی یه متغیری رو const میکنیم در زمان کامپایل رصد میشه و مقدار میگیره.
  • از بین دو نوع فیلد قابل تعریف در کلاس ها , فقط static ها رو که قابلیت رصد شدن در زمان کامپایل دارن رو میشه const کرد و instance filed ها قابلیت const شدن ندارن.

??? پس اگه یه فیلدی در سطج کلاس static const باشه در زمان کامپایل مقدار میگیره.

???اگه یه فیلدی در سطح کلاس static باشه و const نباشه(static خالی ) در زمان کامپایل مقدار نمیگیره و همون run-time مقدار میگیره.

قسمت بعدی : const values.


برای دریافت آموزش های بیشتر و شرکت در چالش های فلاتری, کانال فلاتری Flutter Challenge(چالش فلاتر) رو دنبال کن.