مفاهیم شی گرایی در زبان برنامه نویسی Dart (بخش دوم) – به زبان ساده
این مقاله بخش دوم از سری مطالب راهنمای زبان برنامهنویسی Dart است. در بخش قبلی این مجموعه به معرفی مفاهیم مقدماتی این زبان نوظهور پرداختیم. در این مقاله تلاش خواهیم کرد تا با معرفی مفاهیم شی گرایی از جمله مفهوم کلاس در برنامه نویسی به زبان Dart و همچنین بررسی ژنریک و فایل سیستم، درک خود را از این زبان بسط دهیم.
مبانی شی گرایی در زبان Dart
تا پیش از معرفی زبانهای برنامهنویسی شیءگرا، برنامهها به طور معمول به صورت یک سری دستورهای طولانی نوشته میشدند که از ابتدا به انتها اجرا میشدند و نگهداری آنها بسیار دشوار بود. زبان C، فرترن و کوبول نمونههایی از این زبانها هستند که زبانهای «برنامهنویسی رویهای» (Procedural Programming) نیز نامیده میشوند. همانند مثال دستور آشپزی نودل که در بخش قبلی بررسی کردیم، در این زبانها یک توالی از مراحل باید پیگیری میشد. در هر حال این فرایند برای افراد مبتدی یادگیری آسانی دارد و در مورد برنامههای کوچک نیز موجب میشود که نگهداری برنامه ساده باشد.
با این حال، میخواهیم مثال دستور پخت نودل خود را تقسیم کنیم و تلاش کنیم با استفاده از مفاهیم شیءگرایی آن را مجدداً بسازیم. به جای توصیف مراحل مورد نیاز برای پخت نودل، به بررسی تکتک اشیا در آشپزخانه میپردازیم و کاری که با آنها میتوان انجام داد را در نظر میگیریم. این شیءها شامل قابلمه، بسته نودل، اجاق گاز موارد دیگر هستند. اینک این اشیا مانند برنامههای کوچکی هستند که برای خود دادهها و تابعهایی دارند و با هم دیگر تعامل پیدا میکنند تا برخی وظایف ترکیبی مانند پختن نودل را اجرا کنند. همان طور که میبینید هدف نهایی هر دو مفهوم برنامهنویسی رویهای و شیءگرا یکسان است؛ اما روشی که برای حل مسئله انتخاب میکنند و روشی که به مسئله فکر میکنند، متفاوت است. به علاوه، روش دوم تفکر موجب میشود که کد ما قابلیت استفاده مجدد بیشتری داشته باشد.
برای نمونه اگر بخواهیم فردا نودل خاصی را بخوریم، آیا میتوانیم از همان دستور آشپزی نودل قبلی خود استفاده کنیم؟ البته جزئیات دو نودل مختلف ممکن است متفاوت باشند، اما مسائل کلیتر که با اشیایی مانند قابلمه و اجاق گاز مربوط هستند مانند هم هستند.
امیدواریم مثال فوق به روشنتر شدن مفهوم برنامهنویسی شیءگرا در ذهن شما کمک کرده باشد. همان طور که متوجه شدیم مفهومی که میخواهیم بررسی کنیم مستقل از زبان برنامهنویسی است و مفهوم دیگری است که به نام پارادایم برنامهنویسی میشناسیم. پارادایمهای برنامهنویسی دیگری مانند «برنامهنویسی تابعی» (functional paradigm) نیز وجود دارند. اگر چه این پارادایمهای متفاوت کاربردهای خاصی دارند و شما همواره با شیءگرایی در مسیر خود در حوزه برنامهنویسی وب، برنامهنویسی موبایل و حتی برنامهنویسی بازی برخورد خواهید داشت. اینک نوبت آن رسیده است که وارد دنیای شیءگرایی شویم و به معرفی اشیا و کلاسها بپردازیم.
شیءها و کلاسها
مقصود اصلی از طراحی شیءگرا این بوده است که تفکر در مورد برنامهنویسی از طریق نزدیک ساختن آن به دنیای واقعی تسهیل شود. اینک باید برنامهنویسی کامپیوتر را برای مدتی فراموش کنیم و در مورد این که یک شیء در زندگی واقعی دقیقاً به چه معنا است فکر کنیم؟ یک بسته نودل یا قابلمهای که در آن پخت و پز میکنیم یا حتی اجاق گازی که روشن میشود یا کارخانه نودل همگی قطعاً شیء محسوب میشوند. این شیءها هویت و کاربردهای خاص خود را دارند. آنها متمایز از هم هستند و هر یک مشخصات خاص خود را دارند.
این مشخصات متفاوت به ما کمک میکند که آنها را بر اساس خصوصیاتی مانند رنگ و اندازه از هم تمیز دهیم. این اشیای مختلف رفتارهای متفاوتی نیز دارند مثلاً اجاق گاز میتواند روشن یا خاموش شود. بنابراین دو وجه تمایز یافتیم: خصوصیت و رفتار. این دو وجه به تعریف اشیا در برنامهنویسی شیءگرا میپردازند.
شیء در برنامهنویسی رایانه میتواند شبیه به شیءهای دنیای واقعی باشد، چنان که در بخش قبل توضیح دادیم؛ اما میتواند شیء انتزاعیتری مانند داده، یک تقویم و یا حتی زمان نیز باشد. به این مثال عملی توجه کنید. فرض کنید مشغول نوشتن یک وب اپلیکیشن ساده هستید که از کاربر میخواهد وارد اپلیکیشن شده و ثبتنام کند. سپس یک شیء کاربر از کلاس user ایجاد میکنید (در مورد کلاسها در ادامه صحبت خواهیم کرد ولی فعلاً برای این که مفهوم شیء را بدانیم باید به آنها اشاره کنیم). این کاربر خصوصیتهای مشخصی مانند نام خانوادگی، نام، ایمیل، و رمز عبور دارد و میتواند وارد اپلیکیشن شده و یا ثبتنام کند.
ما نمیتوانیم شیء را بدون صحبت کردن در مورد کلاسها معرفی کنیم، زیرا برای ساخت آنها به کلاسها نیاز داریم. یک کلاس به سادگی نقشه اولیهای از یک قالب یا توصیف چگونگی ساخت یک شیء است. کلاس تا حدودی شبیه به نقشه ساخت یک خانه است. این نقشه خود خانه نیست؛ اما با استفاده از آن میتوان یک و یا حتی چند میلیون خانه ساخت. در مورد کلاسها و شیءها نیز همین تمثیل را میتوان استفاده کرد. ما یک بار به تعریف کلاس میپردازیم و سپس اشیای زیادی را از روی آن کلاس میسازیم. یک کلاس صرفاً به توصیف خصوصیتها و رفتارها میپردازد. در ادامه تعریف یک کلاس را مشاهده میکنید و با استفاده از این کلاس یک شیء در Dart ساخته میشود.
در این کد {...} class User به تعریف حالتها (مشخصات) و رفتار یک User میپردازد. کلیدواژه new برای ایجاد یک شیء از یک کلاس استفاده میشود. در Dart میتوانیم مستقیماً یک شیء را بدون new نیز بسازیم.
به id ،lastname ،firstname ،email و password متغیرهای «وهلهای» (instance) میگوییم که مقدار پیشفرض آنها null است. ()login و ()register متد نام دارند. ()user1.register روش فراخوانی متد یک شیء را نشان میدهد.
چهار مفهوم بنیادی شیءگرایی
در این بخش در مورد چهار مفهوم بنیادی شیءگرایی که تجرید یا انتزاع، کپسولهسازی، وراثت و چندریختی هستند، توضیح میدهیم.
تجرید
اگر به مثال نودل خود بازگردیم، تصور کنید از شنیدن کلمه نودل چه چیزی درک میکنید؟ چه چیزی به ذهن شما میآید؟ یک رشته بلند و دراز که میتوان خورد؟ در واقع از این تصویر نمیتوان نوع خاص نودل را استنباط کرد. همچنین به ما گفته نشده که نودل پخته شده یا خام است. ما صرفاً مفهوم مقدماتی نودل را درک کردهایم و دیگر هیچ خصوصیت مشخصی به ما داده نشده است. از آنجا که قبلاً یک ایده واقعی از نودل داریم میتوانیم آن را درک کنیم. ما قبلاً نودل خوردهایم و از این رو میتوانیم مفهوم نودل را از همه نودلهای واقعی مختلف دنیا تجرید یا انتزاع بکنیم.
این معنی تجرید است، یعنی میتوانیم به جای توجه به گونه خاصی از یک شیء، روی کیفیتهای اساسی آن تمرکز کنیم. بنابراین ایدهای داریم که کاملاً از یک وهله خاص از آن شیء متمایز است و آن را تجرید مینامیم. این همان چیزی است که در برنامهنویسی شیءگرا در زمان ایجاد کلاس استفاده میکنیم. ما برای همه انواع مختلف نودل یک کلاس جداگانه نمیسازیم؛ بلکه یک کلاس برای نودل میسازیم و سپس شیء نودلهای مختلف را از روی آن میسازیم.
کپسولهسازی
خصوصیت و رفتارهای خاصی را انتخاب کنید و آنها را با هم در یک کلاس قرار دهید و دسترسی به آن را از بیرون محدود کنید. یک شیء نباید اطلاعات مربوط به خود را به جز در مواردی که مطلقاً ضروری است افشا کند، و باید دادههایی را که میتوانند از درون کلاس مورد دسترسی قرار گیرند، از دنیای بیرون پنهان کند. برای نمونه ما از دکمههای ریموت کنترل استفاده میکنیم و نتیجه آن را روی نمایشگر تلویزیون میبینیم؛ اما نمیدانیم که درون ریموت چه اتفاقی میافتد و چگونه کار میکند.
این کار «طراحی جعبه سیاه» (black boxing) نام دارد. بدین ترتیب میتوانیم روش انجام کارها را به صورت امنی تغییر دهیم. ما به جای این که در مورد کل برنامه نگران باشیم، صرفاً توجه خود را معطوف به یک کلاس خاص میکنیم. این وضعیت به طور کامل به یک کلاس خاص مربوط است و نه کل برنامه و باید وابستگی درون اپلیکیشن را کاهش دهیم تا با یک تغییر ساده در یک کلاس تأثیری روی بخشهای دیگر نداشته باشد.
وراثت
ما میتوانیم به سادگی یک کلاس جدید بسازیم؛ اما به جای نوشتن همه محتوای آن کلاس، آن را بر مبنای یک کلاس موجود طراحی میکنیم. برای نمونه تصور کنید یک کلاس User در اپلیکیشن خود داریم و در ادامه میخواهیم یک کلاس Admin User جداگانه نیز بسازیم. نکته اینجا است که کلاس User و کلاس Admin User دقیقاً یکسان هستند؛ به جز این که خصوصیتها و رفتارهای بیشتری در کلاس Admin User وجود دارد. به این ترتیب از تجرید استفاده میکنیم و تلاش میکنیم روی پیادهسازی جنبههای مهم کلاس تمرکز کنیم، چون همه کاربران، ادمین نیستند. بنابراین در اینجا دو راهکار وجود دارد که در یکی میتوانیم یک کلاس جدید بسازیم و در دیگری یک کلاس جدید را بر مبنای کلاس User موجود طراحی کنیم. در برنامهنویسی شیءگرا بهتر است کلاسهای جدید را بر مبنای کلاسهای موجود یا به اصطلاح با ارثبری از کلاسهای موجود طراحی کنیم.
معنی وراثت نیز همین است. اینک کلاس جدید admin به طور خودکار همه مشخصهها و رفتارهای کلاس User را دارد و میتوانیم مشخصهها و رفتارهای خاصی را که میخواهیم به آن بیفزاییم. بر اساس اصطلاحات برنامهنویسی شیءگرا اینک کلاس User سوپرکلاس (یا کلاس والد) و کلاس Admin به نام کلاس فرعی (یا کلاس فرزند) نامید میشود. به علاوه میتوانیم کلاسهای زیاد دیگری را نیز بسازیم که از کلاس User مبنای ما ارثبری کنند. اکنون میتوانیم یک شیء User بسازیم یا شیء Admin یا به سادگی هر شیء دیگری را با استفاده از کلاس مبنا بسازیم.
چندریختی
چندریختی یا «پلیمورفیسم» (Polymorphism) به بیان ساده به معنی داشتن شکلهای مختلف است. یعنی میتوانیم از سازه واحدی در موقعیتهای مختلف استفاده کنیم و بر اساس چارچوب خاص آن موقعیت رفتار متناسبی از آن انتظار داشته باشیم. برای نمونه میتوانیم یک کلاس User داشته باشیم و سپس کلاس Admin از این کلاس بر اساس خصوصیتهای و رفتارهای خود ارثبری کند. فرض کنید کلاس User یک متد login دارد که درون آن تعریف شده و کاربر با استفاده از آن وارد اپلیکیشن شده و نام کاربر روی صفحه نمایش مییابد. از آنجا که کلاس Admin فرزند کلاس User است، به طور خودکار این متد را به ارث میبرد.
بنابراین ما درون کلاس Admin به جای متد نمایش نام کاربر یک متد به نام Welcome Admin اضافه میکنیم که متد قبلی را باطل (Override) میکند. اینک اگر متد login را برای کاربر معمولی فراخوانی کنیم، نام وی روی صفحه نمایش مییابد و اگر آن را برای کاربر admin فراخوانی کنیم، پیام خوشامدگویی مدیر نمایش مییابد. تابع Login در چارچوبهای مختلف رفتار متفاوتی دارد و این وضعیت چندریختی نام دارد.
بدین ترتیب با مبانی برنامهنویسی شیءگرا آشنا شدیم و گرچه این بخش طولانی بود؛ اما جای نگرانی نیست چون اینک به پایان رسیده است و شما با مفاهیم بنیادی برنامهنویسی شیءگرا آشنا شدهاید. البته ممکن است قبلاً از آنها استفاده کرده باشید.
سازندهها
بدین ترتیب در بخش قبل با مفهوم شیء آشنا شدیم. شیءهایی که میسازیم چیزی به نام متد چرخه عمر دارند، یعنی متدهایی که از زمان حیات یافتن شیء آغاز میشوند. یکی از این متدها به نام متد «سازنده» (Constructors) شناخته میشود. متد سازنده متد خاصی برای یک کلاس است که مسئول مقداردهی اولیه یک شیء از آن کلاس است. نام آن همان نام کلاس است و در اغلب موارد برای تعیین مقادیر اعضا به صورت تعریف شده از سوی کاربر یا مقادیر پیشفرض استفاده میشود.
در برخی زبانهای دیگر مانند ++C مفهومی به نام deconstructor نیز داریم که به صورت خودکار زمانی که یک شیء که از سوی سازنده ایجاد شده تخریب شود، اجرا میشود. Dart متد deconstructor ندارد، زیرا از مفهومی به نام garbage collector استفاده میکند که مداوماً اجرا شده و همه اشیای ناخواسته را از حافظه پاک میکند. انواع مختلفی از متد سازنده در زبان دارت وجود دارند.
- در کد فوق id_ به این معنی است که فیلد خصوصی این کلاس است و کلاسهای دیگر نمیتوانند به آن دسترسی داشته باشند یعنی نمیتوانیم آن را از بیرون تغییر دهیم. به طور مشابه user._marks = 200.0 در ()main متدی است که تولید خطا میکند. برخی مفاهیم در مورد متدها نیز اعمال میشوند.
- سازندهها برای ارسال اطلاعات و دریافت آنها از کلاس بسیار مفید هستند. در سازنده پارامتری، میتوانیم مقادیر را دریافت کرده و به متغیرهای فیلد کلاس انتساب دهیم.
- پیش از ایجاد یک شیء از کلاس، کد درون سازنده اجرا خواهد شد.
- استفاده از هر دو سازنده پیشفرض و «نامگذاری شده» (Named) در یک کلاس مجاز نیست. ما میتوانیم هر تعداد سازنده نامگذاری شده که دوست داریم داشته باشیم.
- کلیدواژه this به تعریف متغیر فیلدی میپردازد که بخشی از یک شیء است و نه بخشی از تابع.
مفاهیم مهم شیءگرایی در دارت
در این بخش برخی از مفاهیم مهم پارادایم برنامهنویسی شیءگرا در زبان دارت را مورد بررسی قرار میدهیم.
دامنه (Scope)
دامنه در واقع به قابلیت مشاهده متغیرها گفته میشود. هر متغیر بین {...} دامنهای درون آن بلوک کد دارد که به نام دامنه بلوکی شناخته میشود. روش دامنهبندی دارت به نام «دامنهبندی واژگانی» (Lexically scoped) شناخته میشود. منظور از دامنهبندی واژگانی این است که دامنههای فرزند به اغلب متغیرهای اخیراً تعریف شده با نام مشابه دسترسی خواهند داشت. درونیترین دامنه ابتدا مورد جستجو قرار میگیرد و سپس به سمت بیرون عملیات جستجو در دامنههای بعدی تکرار میشود. شکی نیست که جهت ممانعت از بروز مشکل نباید از متغیرهای با نام مشابه استفاده کرد.
Getter و Setter
اینک که با دامنهبندی و متغیرهای فیلد خصوصی با استفاده از _ آشنا شدیم، نوبت آن رسیده است که با مفهوم Getter و Setter آشنا شویم. در کد زیر برخی متغیرهای خصوصی داریم که برای دسترسی از بیرون کلاس به آنها باید روش مناسبی در اختیار داشته باشیم. این روش به نام getter شناخته میشود. جهت تغییر مقادیر خصوصی نیز از متد setter استفاده میشود.
اعضای استاتیک
اعضای استاتیک کلاس هیچ کاری با شیء یا وهله کلاس ندارند و در میان همه وهلههای کلاس مشترک هستند. ما میتوانیم آنها را به صورت مستقیم با استفاده از نام کلاس به جای مقداردهی شیء به دست بیاوریم. متغیرهای استاتیک به نام متغیرهای کلاس و متدهای استاتیک به نام متدهای کلاس نیز شناخته میشوند. متغیرهای استاتیک دارای مقداردهی کُندی هستند، یعنی تا زمانی که در برنامه استفاده نشوند مقداردهی نمیشوند. بنابراین مصرف حافظه آنها بهینه است و به جز در موارد ضروری حافظه را اشغال نمیکنند.
ما از یک متد استاتیک میتوانیم تنها به متد استاتیک و متغیر استاتیک دسترسی داشته باشیم. اما نمیتوانیم به متغیرهای وهلهای نرمال و متدهای کلاس دسترسی پیدا کنیم.
وراثت
همان طور که میدانیم وراثت به سازوکاری گفته میشود که به وسیله آن یک شیء، مشخصههای کلاس والد خود را به دست میآورد. سوپرکلاس هر کلاس یک Object است که پیادهسازی پیشفرض برخی تابعهای از پیش تعریف شده مانند ()toString و getter مربوط به hasCode را ارائه میکند که به نوبه خود کد hash یک شیء را بازگشت میدهد. به طور معمول سه نوع وراثت در دارت ممکن است. «وراثت منفرد» که در آن یک کلاس از کلاس دیگر ارث میبرد، «وراثت چند سطحی» که در آن یک کلاس از کلاس دیگر ارث میبرد که آن کلاس نیز به نوبه خود از کلاس دیگری ارثبری کرده است، و «وراثت سلسلهمراتبی» که در آن دو یا چند کلاس از یک کلاس والد ارث میبرند.
به علاوه همان طور که قبلاً دیدیم با استفاده از overriding متد میتوانیم در یک کلاس فرزند، متدی را که از کلاس والد به ارث رسیده بازتعریف کنیم و کامپایلر نیز به متد override شده اولویت بالاتری میدهد.
- در کد فوق کلیدواژه extends برای ارثبری از کلاس والد استفاده میشود.
- کلیدواژه super در صورتی استفاده میشود که بخواهیم متد یا متغیر والد را از کلاس فرزند فراخوانی کنیم.
- در این کد متد ()canReproduce چندین بار override شده است و اگر آن متد را از شیء متفاوتی فراخوانی کنیم، به دلیل چندریختی نتیجه مختلفی دریافت میکنیم.
Mixin
Mixin زمانی استفاده میشود که میخواهیم وراثتهای چندگانه داشته باشیم. این یکی از ویژگیهای خاص دارت محسوب میشود. Mixin-ها روشی برای استفاده مجدد از کد کلاس در سلسلهمراتبهای چندگانه کلاس هستند. این یک موضوع پیشرفته است که در مقالات آتی مجله فرادرس در مورد آن بیشتر صحبت خواهیم کرد. فعلاً به کد زیر توجه کنید تا با مفاهیم مقدماتی Mixin آشنا شویم.
یکی از الزامات mixin این است که کلاس باید مستقل باشد. برای مثال در کد فوق کلاس Reptile چنین وضعیتی دارد و از کلاس دیگری به ارث نرسیده است. بنابراین وقتی از mixin صحبت میکنیم، یعنی میتوانیم متد کلاس دیگری را بدون ارثبری از آن مورد استفاده قرار دهیم.
اینترفیسها
یک اینترفیس به سادگی به تماس بین دو کلاس گفته میشود. یک اینترفیس زمانی استفاده میشود که یک پیادهسازی مستحکمی از همه تابعهای آن، درون کلاس فرعیاش وجود داشته باشد. این الزام وجود دارد که همه متدها در کلاس پیادهسازی override شوند. ضمناً میتوانیم کلاسهای چندگانهای را implement کنیم؛ اما نمیتوانیم در طی وراثت کلاسهای چندگانه را extend کنیم. به بیان سادهتر وقتی یک کلاس را ارثبری میکنیم، همه مشخصههای کلاس مبنا را به ارث میبریم، اما وقتی کلاسی را پیادهسازی میکنیم باید آن مشخصهها را خودمان پیادهسازی کنیم.
تجرید
در «تجرید» (abstraction) ما در عمل یک کلاس را ایجاد نمیکنیم؛ بلکه ایده یا مفهوم آن را میسازیم. این وضعت شبیه به اینترفیس است؛ اما در عمل از آنها ارثبری میکنیم. برای ایجاد یک متد مجرد به جای بدنه متد باید از نقطهویرگول استفاده کنیم. یک متد مجرد تنها در یک کلاس مجرد میتواند تعریف شود. ما باید متدهای مجرد را در کلاسهای فرعی override کنیم. برای یک کلاس مجرد از کلیدواژه abstract برای اعلان کلاس استفاده میکنیم. این کلاسها میتوانند متدهای مجرد، متدهای معمولی و متغیرهای وهلهای داشته باشند. کلاس مجرد نمیتواند وهلهسازی شود، یعنی نمیتوان از روی آن شیئی ساخت.
ژنریکها
اگر بخش اول این راهنما را مطالعه کرده باشید، پس قبلاً از «ژنریکها» (Generics) استفاده کردهاید.
ما لیستی داریم که یک کلاس است و این کلاس یک کلاس ژنریک است و از این رو باید در خط اول آن یک نوع به آن بدهیم که از نوع String استفاده کردهایم. در این مورد نیز از همان ساختار استفاده میکنیم؛ اما به جای آن یک نوع int ارسال میکنیم. همان طور که میبینید یک کلاس یکسان میتواند به عنوان int و همچنین String استفاده شود. این کار ژنریک نام دارد. یعنی کد میتواند انواع مختلف را بر اساس این که چه کاری باید انجام دهد مدیریت کند.
در کد فوق T اختصاری برای Type یعنی نوع است. ما میتوانیم هر حرفی را در خط زیر بنویسیم:
در ادامه یک مثال از برنامهنویسی ژنریک را مشاهده میکنید. در این مثال میتوانیم مقدار int را به double تغییر دهیم و تغییری در کارکرد برنامه ایجاد نمیشود.
مثالی از کلاس ژنریک
در ادامه میخواهیم یک کلاس ژنریک به نام {.. }<Counter<T extends num ایجاد کنیم که گروهی از عملیات مانند addAll و total را اجرا میکند.
فایل سیستم
برای اجرای اقداماتی مانند خواندن و نوشتن فایلها باید بستهای جداگانهای به نام dart:io را ایمپورت کنیم.
در کد فوق (/) دایرکتوری ریشه لینوکس است. در مورد ویندوز باید از c:\ استفاده کنیم.
در مورد Sync و Async که به برنامهنویسی همگام و ناهمگام مرتبط هستند در بخش بعدی این مقاله صحبت خواهیم کرد. فعلاً کافی است بدانیم که عملیات I/O میتواند هم به صورت همگام و هم ناهمگام اجرا شود. منظور از همگام این است که همه چیز به صورت یکباره رخ میدهد و ناهمگام نیز به این معنی است که کارها میتوانند به صورت هر بار یکی اجرا شوند.
()dir.existSync به این معنی است که باید مدتی منتظر بمانیم و پس از این که این دستور به پایان رسید، دستور بعدی اجرا خواهد شد.
()Directory.systemTemp.createTempSync به این معنی است که یک عضو استاتیک کلاس Directory فراخوانی شده است و از این رو باید یک دایرکتوری موقت را به صورت همگام ایجاد کنیم. در صورت وجود دایرکتوری آن را پاک میکنیم.
کد فوق کاملاً گویا است. در این کد دایرکتوری جاری را دریافت کرده و همه فایلها را به صورت بازگشتی مرتبسازی کرده و وضعیت هر فایل مانند اندازه و نوع را نمایش میدهیم.
زمانی که میخواهیم چیزی را در یک فایل بنویسیم میتوانیم آن چیز را به فایل الحاق کنیم (یعنی به انتهای فایل اضافه کنیم) و یا آن را به طور کامل بنویسیم یعنی کل محتوای فایل را پاک کرده و از نو آن را بنویسیم.
RandomAccessFile به این معنی است که میتوانیم از هر جایی به صورت تصادفی به فایل دسترسی داشته باشیم. ما این فایل با دسترسی تصادفی را ایجاد میکنیم و سپس آن را به صورت ناهمگام باز میکنیم و یک حالت خاص که در اینجا APPEND است به آن میدهیم. سپس رشته مورد نظر را به آن الحاق میکنیم.
()closeSync صرفاً به منظور بستن فایل استفاده میشود. ممکن است بپرسید که چرا باید فایل را ببندیم؟ دلیل این مسئله آن است که ما اطلاعات را در یک فایل قرار دادهایم و ممکن است بیدرنگ روی دیسک نوشته نشود. از این رو باید فایل را ببندیم تا این فرایند به نوبه خود تابع ()flushSync را فراخوانی کند که همه چیز را روی دیسک مینویسد. برای خواندن اطلاعات از یک فایل میتوانیم تابع ()readAsStringSync را روی شیء آن فایل فراخوانی کنیم.
نتیجهگیری
بدین ترتیب به پایان این مقاله نسبتاً بلند میرسیم. اگر به قدر کافی تمرکز کنید و مفاهیم مطرح شده را تمرین کنید، به راحتی میتوانید بر آنها تسلط پیدا کنید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزش های برنامه نویسی
- مفاهیم مقدماتی زبان برنامه نویسی دارت (Dart) – بخش اول
- مجموعه آموزش های مهندسی نرم افزار
- آموزش گوگل فلاتر (Flutter ): ساخت اپلیکیشن دستورهای آشپزی
- مفاهیم مقدماتی فلاتر (Flutter) — به زبان ساده
- آشنایی با Garbage Collector در فلاتر (Flutter) — راهنمای پیشرفته
- مفهوم کلاس در برنامه نویسی — همراه با نمونه مثال عملی
==
بسیار عالی ممنون از توضیحات خوبتون
آینده زبان دارت چگونه پیش بینی میکنید؟