آموزش جاوا (فصل ۱۳)

آشنایی با مفهوم Interface در زبان برنامه‌نویسی جاوا


Interface مفهومی است در زبان‌های برنامه‌نویسی که این امکان را در اختیارمان می‌گذارد تا توسعهٔ کلاس‌ها هرگز به صورت سلیقه‌ای صورت نگیرد بلکه کلیهٔ دولوپرهایی که در یک تیم نرم‌افزاری روی پروژه‌ای واحد کار می‌کنند موظف به تبعیت از چارچوبی خواهند بود که در اینترفیس‌های مختلف ترسیم شده‌اند. در واقع، اینترفیس‌ها مشابه کلاس‌ها تعریف می‌شوند اما برخی تفاوت‌هایی با یکدیگر دارند که در ادامه به بررسی این شباهت‌ها و تفاوت‌ها می‌پردازیم.

به طور کلی، از جمله شباهت‌های مابین کلاس‌ها و اینترفیس‌ها می‌توان به موارد زیر اشاره کرد:

– همچون کلاس‌ها، در یک اینترفیس می‌توان به تعداد دلخواه متد تعریف کرد.
– همچون کلاس‌ها، در یک اینترفیس می‌توان متغیرهای فیلد تعریف کرد.
– همچون کلاس‌ها، یک اینترفیس قابلیت ارث‌بری از روی اینترفیسی دیگر را دارا است.
– نام فایل مربوط به اینترفیس دقیقاً هم‌نام با اینترفیس می‌باشد به علاوه اینکه پسوند فایل مذکور نیز java. است.

همان‌طور که پیش‌تر اشاره کردیم، اینترفیس‌ها در زبان برنامه‌نویس جاوا همانند کلاس‌ها می‌باشند اما برخی تفاوت‌ها نیز مابین آن‌ها وجود دارد که برخی از مهم‌ترین آن‌ها عبارتند از:

– یک کلاس فقط و فقط می‌تواند از یک کلاس دیگر ارث‌بری کند در حالی که در یک کلاس می‌توان بیش از یک اینترفیس را به اصطلاح ایمپلیمنت کرد.
– یک کلاس‌ می‌تواند حاوی متدهایی دارای نام و بدنۀ مربوط به دستورات داخلی باشد اما در اینترفیس‌ها دستوری داخل بدنهٔ متدها نوشته نمی‌شود که چنین متدهایی تحت عنوان متدهای Abstract نامیده می‌شوند (در عین حال، در نسخۀ 8 به بعد جاوا امکان تعریف دستورات داخلی برای برخی متدهای فراهم شده است.)
– بر خلاف کلاس‌ها، از روی اینترفیس‌ها نمی‌توان آبجکت ساخت اما چنانچه کلاسی از روی اینترفیسی ایمپلیمنت شده باشد، می‌توان از روی اینترفیس مد نظر آبجکتی ساخته و از آن به عنوان جایگزینی برای آبجکت ساخته‌شده از روی کلاسی استفاده کرد که اینترفیس مذکور را ایمپلیمنت کرده است. 
– بر خلاف کلاس‌ها، اینترفیس‌ها قابلیت ارث‌بری از روی چندین اینترفیس را دارند که این امر قابلیت Multiple Inheritance یا «ارث‌بری چندگانه» را برای زبان برنامه‌نویسی جاوا فراهم کرده است.
– بر خلاف کلاس‌ها، یک اینترفیس صرفاً سطح دسترسی public می‌تواند داشته باشد.

نحوۀ ایجاد یک اینترفیس در زبان برنامه‌نویسی جاوا

در ادامۀ این آموزش قصد داریم تا نحوۀ ایجاد یک اینترفیس در زبان برنامه‌نوسی جاوا را تشریح نماییم که برای این منظور پروژه‌ای تحت عنوان Interface ایجاد کرده و اینترفیسی به نام ProgrammerOne در آن می‌سازیم به طوری که در این اینترفیس قصد داریم تا وظایف کاری یک برنامه‌‌نویس را پیاده‌سازی کنیم که وظیفۀ طراحی رابط کاربری یک نرم‌افزار را بر عهده دارد که در ابتدا کد مربوط به آن را به صورت زیر تکمیل می‌کنیم:

public interface ProgrammerOne {
    public String myString = "Programmer one has to design the UI.";
    public void designTheUI();
}

همان‌طور که در کد فوق ملاحظه می‌کنیم، برای ساخت یک اینترفیس می‌باید از کلیدواژۀ public استفاده کرده سپس کلیدواژهٔ interface را آورده و در ادامه یک نام (در این مثال ProgrammerOne) برای آن انتخاب می‌کنیم که بدین معنی است که این اینترفیس توسط تمامی کلاس‌های موجود در تمامی پکیج‌های پروژه قابل‌دسترسی است و در ادامه همانند ساختار یک کلاس، از علائم { } استفاده کرده و متدهای مورد نیاز را داخل آن تعریف می‌کنیم.

به طور مثال، در کد فوق آبجکتی تحت عنوان myString از روی کلاس String ساخته و استرینگ «.Programmer one has to design the UI» را بدان منتسب کرده‌ایم که به منزلۀ یک متغیر فیلد برای این اینترفیس می‌باشد و در ادامه متدی تحت عنوان ()designTheUI تعریف کرده‌ایم که بر خلاف متدهای تعریف‌شده در داخل کلاس‌ها، دارای علائم{ } نیست و این مسئله از آنجایی ناشی می‌شود که متدهای داخل یک اینترفیس صرفاً دارای یک Signature (نام متد و پارامترهای ورودی مد نظر) می‌باشند و دستورات داخلی آن‌ها در کلاس‌هایی پیاده‌سازی می‌شوند که از اینترفیس مد نظر به اصطلاح ایمپلیمنت شده باشند. به عبارت دیگر، متدهای داخل اینترفیس فقط به صورت انتزاعی تعریف شده سپس وظایف متد مد نظر داخل دو علامت { } در کلاسی پیاده‌سازی می‌شود که قرار است تا آن اینترفیس را ایمپلیمنت کند (جهت کسب اطلاعات بیشتر در رابطه با متغیرهای فیلد به آموزش آشنایی با متغیرهای Local و Field در زبان برنامه‌نویسی جاوا مراجعه نمایید.)این بخش از محتوا مخصوص کاربرانی است که ثبت‌نام کرده‌اند.
جهت مشاهدهٔ این بخش از محتوا لاگین نمایید.

در این آموزش ابتدا به بررسی نحوۀ ایجاد یک اینترفیس پرداخته و در ادامه دیدیم که چگونه می‌توان آن را در کلاسی دیگری به اصطلاح ایمپلیمنت کرد؛ سپس نحوۀ ایمپلیمنت کردن چند اینترفیس در یک کلاس را تشریح کردیم. در ادامه، نحوۀ ارث‌بری دو اینترفیس از یکدیگر را مورد بررسی قرار دادیم و گفتیم که برای این منظور نیز مشابه ارث‌بری دو کلاس از یکدیگر عمل کرده و از کیورد extends استفاده می‌نماییم و در پایان نیز به بررسی مهم‌ترین وجه تمایز اینترفیس‌ها با کلاس‌ها پرداخته و دیدیم که چگونه می‌توان برای یک اینترفیس قابلیت ارث‌بری از چندین اینترفیس را فراهم نمود و گفتیم که این موضوع قابلیت ارث‌بری چندگانه را برای کلاس‌ها در زبان جاوا نیز فراهم می‌نماید.

آشنایی با مفهوم Thread در زبان برنامه‌نویسی جاوا


در این آموزش یکی از مباحث بسیار مهم در زبان برنامه‌نویسی جاوا تحت عنوان Thread را معرفی کرده و مقدمه‌ای از کاربرد آن در اجرای تَسک‌های نوشته‌شده در برنامه‌های جاوا را تشریح می‌کنیم. به طور کلی، می‌توان گفت که تِرِدها دارای کاربردهای فراوانی هستند که از آن جمله می‌توان به توسعۀ گیم، اپلیکیشن‌های تحت وب و غیره اشاره کرد (جهت کسب اطلاعات بیشتر در رابطه با نحوۀ اجرای برنامه به صورت مالتی‌تِرِد به مقالۀ آشنایی با مفاهیم Thread ،Process و نحوۀ کارکرد Multithreading مراجعه نمایید.) در واقع، زمانی از تِرِدها در پروسهٔ توسعهٔ نرم‌افزار استفاده می‌کنیم که بخواهیم برنامه‌ای طراحی کنیم تا در آن بیش از یک کار را به طور هم‌زمان پیش ببریم که برای این منظور نیز کلاسی تحت عنوانThread در زبان برنامه‌نویسی جاوا تعبیه شده است.

حال برای درک بهتر مفهوم تِرِدها، مثالی را مد نظر قرار می‌دهیم بدین صورت که وقتی یک فایل ویدئویی را به صورت آنلاین تماشا می‌کنیم، نیازی نیست تا صبر کنیم تا فایل کاملاً بارگذاری شود بلکه پخش ویدئو شروع شده و هم‌زمان با نمایش ویدئو بارگذاری بخش‌های دیگر آن نیز انجام می‌شوند. به عبارت دیگر، دو کار نمایش ویدئو و بارگذاری آن به صورت هم‌زمان صورت می‌گیرند که این موضوع دقیقاً به کاربرد تِرِدها در پیشبرد دو تَسک به صورت هم‌زمان اشاره دارد.

در حقیقت، به طور خلاصه می‌توان گفت که با استفاده از تِرِدها می‌توانیم نرم‌افزاری طراحی کنیم تا به جای انتظار برای تکمیل انجام یک کار سپس آغاز کار بعدی، هر دو کار به صورت هم‌زمان پیش روند که اهمیت چنین مسئله‌ای در توسعهٔ گیم دو چندان می‌گردد. از سوی دیگر، تِرِدها صرفاً در بازی‌سازی کاربرد نداشته و در حوزۀ اپلیکیشن‌های تحت وب و دسکتاپ نیز کاربردهای فراوانی دارند. به طور مثال، فرض کنیم که یک اپلیکیشن تحت وب با زبان جاوا طراحی کرده‌ایم که در نقش یک وب سرور بوده و وظیفۀ هندل کردن بیش از یک ریکوئست (درخواست) در آنِ واحد را دارا است که این کار به سادگی با استفاده از مفهوم تِرِدها در زبان جاوا امکان‌پذیر می‌باشد.

حال در ادامه قصد داریم تا ببینیم که چگونه می‌توان به صورت عملی یک تِرِد در زبان برنامه‌نویسی جاوا ایجاد کرد و اجرای برنامه‌ها با استفاده از چند تِرِد چه مزایایی دارا است. به طور کلی، می‌توان گفت که پیاده‌سازی تِرِدها در زبان برنامه‌نویسی جاوا به دو روش مختلف امکان‌پذیر می‌باشد که عبارتند از:

– روش اول بدین صورت است که کلاسی ایجاد کرده سپس کلاس مذکور ویژگی‌های خود را از کلاس Thread در زبان جاوا به ارث می‌برد. 
– در روش دوم کلاسی ایجاد کرده و آن را از روی اینترفیسی تحت عنوان Runnable ایمپلیمنت می‌کنیم که در چنین شرایطی می‌توانیم بدون ارث‌بری از کلاس Thread اقدام به ساخت تِرِد نماییم.

در ادامۀ این آموزش و به منظور درک سازوکار تِرِدها، هر دو روش را مورد بررسی قرار خواهیم داد.این بخش از محتوا مخصوص کاربرانی است که ثبت‌نام کرده‌اند.
جهت مشاهدهٔ این بخش از محتوا لاگین نمایید.

در این آموزش به بررسی کاربرد تِرِدها در اجرای برنامه پرداخته و نحوۀ ایجاد یک تِرِد با به‌کارگیری دو روش مختلف در زبان برنامه‌نویسی جاوا را آموختیم و دیدیم که چگونه می‌توان با استفاده از هر یک از روش‌های مذکور برنامه‌ای را پیاده‌سازی کرد که به صورت مالتی‌تِرِد اجرا شود. دانلود فایل‌های تمرین

آشنایی با نحوۀ کنترل ترتیب اجرای تِرِدها در زبان برنامه‌نویسی جاوا


در آموزش‌ گذشته با مفاهیم تِرِد و مالتی‌تِرِدینگ در زبان برنامه‌نویسی جاوا آشنا شده و نحوۀ ایجاد دو تِرِد و اجرای آن‌ها به صورت هم‌زمان را آموختیم اما در این آموزش قصد داریم تا روشی به منظور کنترل ترتیب اجرای تِرِدهای برنامه ارائه نماییم. همان‌طور که در آموزش آشنایی با مفهوم Thread در زبان برنامه‌نویسی جاوا توضیح دادیم، دو روش برای ساخت تِرِد در زبان جاوا وجود دارد که در این آموزش از روش اول به منظور ایجاد تِرِدها استفاده کرده و بدین ترتیب یکسری کلاس جهت ارث‌بری از کلاس Thread زبان جاوا تعریف کرده و در ادامه نحوۀ کنترل ترتیب اجرای تِرِدها را مورد بررسی قرار خواهیم داد.

در همین راستا، ابتدا پروژه‌ای تحت عنوان ControllingThreadExecution در محیط برنامه‌نویسی اکلیپس ایجاد کرده و در آن کلاسی به نام HowToControlThreads می‌سازیم به طوری که در کد زیر داریم:

public class HowToControlThreads extends Thread {
    @Override
    public void run() {
        System.out.println("This is text from first thread 1");
        System.out.println("This is text from first thread 2");
        System.out.println("This is text from first thread 3");
        System.out.println("This is text from first thread 4");
        System.out.println("This is text from first thread 5");
        System.out.println("This is text from first thread 6");
    }
}

در کد فوق، ابتدا نام کلاس را نوشته و در ادامه کیورد extends سپس نام کلاس Thread را نوشته‌ایم که بدین ترتیب کلاس HowToControlThreads از کلاس Thread ارث‌بری کرده و در ادامه متد ()run از این کلاس را جهت پیاده‌سازی دستورات مد نظر خود اُورراید کرده‌ایم و در آن دستوراتی مبنی بر چاپ استرینگ‌های فوق را نوشته‌ایم که در صورت فراخوانی متد ()run استرینگ‌های مربوطه را در کنسول نمایش می‌دهد.این بخش از محتوا مخصوص کاربرانی است که ثبت‌نام کرده‌اند.
جهت مشاهدهٔ این بخش از محتوا لاگین نمایید.

در این آموزش ابتدا به بررسی ترتیب اجرای تِرِدها در برنامه‌های پرداختیم که به صورت مالتی‌تِرِد اجرا می‌شوند سپس به منظور کنترل ترتیب اجرای تَسک‌ها توسط تِرِدهای ایجادشده، اینترفیسی تحت عنوان ExecutorService را معرفی کرده و گفتیم که جهت دسترسی به متدهای پیاده‌سازی‌شدۀ این اینترفیس، به کلاس Executors مراجعه کرده و متدهای مورد نیاز خود را فراخوانی می‌نماییم. در ادامه، متد ()newSingleThreadExecutor را فراخوانی کردیم که این وظیفه را دارا است تا یک تِرِد ایجاد کرده و اجرای تمامی تَسک‌های برنامه را محدود به آن تِرِد نماید. دانلود فایل‌های تمرین


آشنایی با مفهوم Concurrency در زبان برنامه‌نویسی جاوا


یکی از تفاوت‌های عمدۀ خانم‌ها و آقایان به میزان توانایی آن‌ها در انجام کارهای به صورت اصطلاحاً Concurrent یا «هم‌زمان» مربوط می‌شود که پیش از توضیح پیرامون این مسئله، دو تصویر زیر را با یکدیگر مقایسه می‌کنیم:

در تصویر فوق، آقایی را می‌بینیم که قصد دارد تا چند کار را به صورت هم‌زمان انجام دهد و همان‌طور که چهرۀ وی نشان می‌دهد، کاملاً مشخص است که تا چه حدی در انجام این کار موفق است! در واقع، علت عدم توانایی آقایان در انجام چندین کار به صورت هم‌زمان در این است که اکثر ایشان توانایی تمرکز روی تنها یک یا دو کار متفاوت را به صورت هم‌زمان دارند و این در صورتی است که اگر بیش از یک کار به ایشان تفویض شود، کیفیت کارشان به مراتب پایین‌تر می‌آید. حال با مد نظر قرار دادن تصویر زیر می‌بینیم که این وضعیت در مورد خانم‌ها به چه صورت است:

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

زبان برنامه‌نویسی جاوا نیز قابلیت انجام تَسک‌ها به صورت Concurrent را دارا است. در حقیقت، زبان جاوا از همان ابتدای شکل‌گیری دارای قابلیت Concurrency بود. به عبارت دیگر، طراحان این زبان برنامه‌نویسی قصد داشتند تا زبانی را توسعه دهند که امکان اجرای چندین تَسک را به طور هم‌زمان به برنامه‌نویسان و توسعه‌دهندگان بدهد (لازم به یادآوری است که در نسخۀ جاوای 5 به بعد، کلاس‌ها و متدهای از پیش تعریف‌شدۀ پیشرفته‌ای برای استفاده از مفهوم Concurrency به این زبان اضافه شده‌اند.)

به طور کلی، مفهوم کانکارنسی در زبان جاوا منجر به توسعۀ برنامه‌هایی می‌گردد که تعامل بیشتری با کاربر دارند. برای مثال، فرض می‌کنیم که برنامه‌ای طراحی کرده‌ایم که می‌باید فایلی را از طریق شبکه دانلود کند و پس از تکمیل فایل آن را پخش نماید که در چنین شرایطی چنانچه برنامۀ مورد نظر قابلیت اجرا به صورت کانکارنت را نداشته باشد، می‌باید مدت زمان قابل‌توجهی را بسته به حجم فایل منتظر دانلود آن مانده سپس فایل مذکور را پخش نماید اما اگر برنامۀ مد نظر را به صورت کانکارنت پیاده‌سازی نماییم، این دو کار به صورت هم‌زمان انجام می‌شود بدین معنی که در هنگام دانلود شدن فایل، برنامه بخش دانلودشده از آن را پخش کرده و بدین ترتیب تجربۀ کاربری خوبی برای کاربران رقم می‌خورد.

به طور کلی، تمامی برنامه‌های نوشته‌شده با زبان جاوا حداقل دارای یک تِرِد هستند که تحت عنوان Main Thread یا «تِرِد اصلی» شناخته می‌شود و این تِرِد اصلی می‌تواند دیگر تِرِدها را در خود جای دهد و همان‌طور که در آموزش‌های پیشین در مباحث مرتبط با تِرِدها دیدیم، می‌توانیم چندین تِرِد را در متد ()main ایجاد کنیم به طوری که متد ()mainرا می‌توان به عنوان «تِرِد اصلی» برنامه خود نیز در نظر بگیریم.

حال فرض کنیم که برنامه‌ای داریم که به صورت کانکارنت اجرا می‌شود. به عبارت دیگر، این برنامه حاوی چندین تِرِد است که هر کدام وظیفۀ انجام تَسک خاصی را بر عهده دارند که در چنین شرایطی می‌باید سازوکاری داشته باشیم که از تداخل عملکرد تِرِدها جلوگیری به عمل آورد و برای رفع مسائلی از این دست به مفهومی تحت عنوان Synchronization نیاز داریم که معادل فارسی این واژه «هم‌زمانی» می‌باشد. در واقع، هم‌زمانی مابین تِرِدها این اطمینان را به ما می‌دهد که مثلاً زمانی که یک تِرِد در حال ویرایش یک فایل و یا ایجاد یک فایل جدید است، سایر تِرِدها امکان دسترسی به آن فایل را نداشته و می‌باید منتظر بمانند تا کار تِرِد مذکور به پایان برسد. در واقع، علت به‌کارگیری مفهوم Synchronization نیز این است که هر دو تِرِد به اطلاعات یکسانی دسترسی دارند و چنانچه امکان دخالت در کار یکدیگر داشته باشند، می‌باید انتظار مشکلاتی را در برنامۀ خود داشته باشیم.

مطالب مرتبط

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *