انتزاع به معنای مفهوم کلی است … فرض کنید به مجلسی وارد شده اید,کسی را نمیشناسید و اطلاعی از وجوه مشترک میان افراد ندارید,در این حالت میگوییم تمام افراد ان مجلسه انسان هستند ,انسانیت مفهوم کلی است که بر همه ی انها صدق میکند در حالی که برای مثال سن و قد شخص خاصی در ان مجلس را نمیتوان به عنوان وجه مشترک میان افراد ان مجلس به حساب اورد ;چرا که شخص دیگر ,قد و وزن این شخص را ندارد .
اشکال هندسی را تصور کنید ;مثلث و مربع و دایره… هرکدام تفاوت هایی با یکدیگر دارند,به عنوان مثال مجموع اندازه ی زاویه های مربع با مثلث یکسان نیست بنابراین به مجرد آنکه سعی میکنیم وجه مشترک میان انهارا در یابیم با کمی فکر به این نکته میرسیم که هر سه شکل هستند(این گفته بسیار کلی گویی هست و منظور از انتزاع هم همین میباشد). در این حالت میگوییم شکل و انسان مفاهیمی انتزاعی هستند .
مفاهیم بالا در برنامه نویسی هم بسیار مورد استفاده قرار میگیرند,توابع انتزاعی زمانی مورد استفاده قرار میگیرند که ما از نحوه ی تعریف ان اطلاع نداریم اما میدانیم یک ویژگی مشترک بین شی های ما میباشد,برای مثال ویژگی مشترک بین حیوانات در اوردن صدا میباشد ,متدی که برای به صدا در اوردن حیوان مورد استفاده قرار میگیرد ,برای حیوانات مختلف صدا یکسان نیست و هر حیوان به شیوه ی خود متد مورد نظر را پیاده سازی میکند ,یا برای مثال تمام اشکال هندسی دارای زاویه هستند اما تعداد و اندازه ی آنها یکسان نیست
هنگامی که در مورد ساخت یک کلاس در جاوا فکر میکنیم ,اولین چیزی که به ذهن ما خطور میکند این است که ان کلاس با هدف ساخت شی و استفاده در کلاس های دیگر ایجاد میشود. با این همه , گاهی اوقات فقط کلاس ها تعریف میشوند و برنامه نویسان هرگز قصد ندارند هیچ شی را نمونه سازی کنند. چنین کلاس هایی که کلاس انتزاعی نامیده میشوند تنها برای رساندن مفهوم کلیت و وجه های مشترک بین اشیا هستند . این کلاس ها معمولا به عنوان سوپرکلاس ها (کلاس های پدر) در سلسه مراتب توارث بکار گرفته میشوند, از این رو معمولا با عنوان سوپر کلاس های انتزاعی شناخته می شوند.
هدف از یک کلاس انتزاعی ایجاد یک سوپر کلاس مناسب است که قرار است بین کلاس ها طرح مشترکی را به اشتراک بگذارد. کلاس هایی که میتوانند در نمونه سازی شی ها بکار گرفته شوند , کلاس های مقید (غیر انتزاعی) نام دارند.با اینکه کلاس های غیر انتزاعی نیز قابلیت سوپر کلاس بودن را دارند اما کلاس های فرزند اجباری به پیاده سازی متد های ان ها ندارند و درواقع کلاس های انتزاعی کلاس های فرزند را اجبار به پیاده سازی متد های مورد نظر میکنند
چنین کلاس هایی تدارک بیننده پیاده سازی هر متد هستند که اعلان می کنند (برخی از پیاده سازی ها را می توان به ارث برد).
برای مثال میتوانیم یک سوپر کلاس انتزاعی بنام TwoDimensionalShape و زیر کلاس های مقید همانند Square و Triangle داشته باشیم. همچنین میتوانیم یک سوپر کلاس انتزاعی بنام ThreeDimensionalShape و زیر کلاس های مقید همانند Cube, Sphere, Testrahedron داشته باشیم. سوپر کلاس های انتزاعی برای تعریف شی های واقعی بسیار کلی هستند , از اینرو قبل از اینکه شی را نمونه سازی کنیم باید با دقت در مورد ان فکر کنیم.
برای مثال اگر شخصی به شما بگوید شکلی دو بعدی ترسیم کنید باید بپرسید چه شکلی؟
تعریف یک کلاس همراه با کلمه کلیدی abstract آن را بصورت یک کلاس انتزاعی ایجاد میکند. معمولا یک کلاس انتزاعی حاوی یک یا چند متد انتزاعی است. متد انتزاعی متدی است که با کلمه کلیدی abstract در اعلان خود همراه شده باشد , همانند :
public abstract class Shape{ public void method1(){// non abstract method } public abstract void draw(); // abstract method
}
متد های انتزاعی قابل پیاده سازی در خود کلاس نیستند. هر کلاسی که حاوی هر متد انتزاعی است باید به صورت یک کلاس انتزاعی تعریف شود حتی اگر کلاس حاوی متد های مقید(همان متد های غیر انتزاعی) باشد. همچنین هر زیر کلاس از یک سوپر کلاس انتزاعی باید پیاده سازی ای از متد های انتزاعی سوپر کلاس را فراهم اورد (در مثال بالا زیر کلاسی که از کلاس Shape ارث بری کرده است الزاما باید متد draw را پیاده سازی کند اما الزامی به پیاده سازی method1 نمیباشد چرا که ان متد ,متدی abstract نمیباشدو خود یک متد مقید محسوب میشود و در کلاس Shape پیاده سازی شده است , در صورت تمایل کلاس فرزند میتواند آن را بازنویسی کند) . سازنده ها و متد های استاتیک نمی توانند بصورت abstract اعلان شوند. سازنده ها ارث بری ندارند از این رو هرگز نمیتوان یک سازنده abstract را پیاده سازی کرد. به همین ترتیب زیر کلاس ها نمیتوانند متد های استاتیک را override یا تعریف مجدد کنند و از اینرو نمیتوان یک متد استاتیک abstract را پیاده سازی کرد
احتمالا این سوال برای شما پیش امده که به چه دلیل نمیتوان متد های استاتیک را override کرد…
به دلیل اینکه متد های استاتیک در جاوا به اشیاء ساخته شده از یک کلاس تعلق ندارند و اصطلاحا متد های در سطح کلاس هستند و نمی توان آنها را در کلاس فرزند override کرد و اگر یک متد استاتیک در کلاس فرزند دقیقا با همان امضای متد کلاس پدر وجود داشته باشد خطایی رخ نمی دهد و برنامه بدرستی کامپایل می شود.
در این موارد گفته می شود کد متد فرزند متد پدر را hide کرده است و به این کار override گفته نمی شود چون هنوز متد کلاس پدر در سطح همان کلاس قابل دسترسی است.
با توجه به اینکه اینترفیس ها از نسخه ی Jdk 8 به بعد میتوانند متد هایی با پیاده سازی داشته باشند (default method) چه زمانی از abstract class و چه زمانی از interface استفاده کنیم ؟
تفاوت بنیادین اینترفیس و کلاس abstract در این است که اولا کلاس آبسترکت میتواند constructor (سازنده) داشته باشد و این بدین معناست که میتواند مقادیری درون خود نگه دارد و بعد ها بنا به دلایلی از آن استفاده کند.. همچنین اعلام میدارد یک شی نمیتواند بوجود آید مگر با فلان مقادیر : مثلا فرض کنید Human نیاز به جنسیت دارد .. پر واضح است که یک انسان وجود ندارد مگر اینکه جنسیت آن مشخص باشد .انسانی بدنیا نمی آید که فاقد جنسیت باشد
بنابراین در abstract class ما یک سازنده میذاریم و جنسیت رو از کلاس فرزند میگیریم (فرضا فرزند میتونه کلاس مونث و مذکر باشد)
اما اگر Human را اینترفیس تعریف میکردیم درواقع چنین مفهومی را نقض میکردیم چرا که اینترفیس ها فاقد سازنده هستند.
به بیان ساده یک ابسترکت کلاس میگوید آن آبجکت دقیقا کی(چی) است
اما اینترفیس میگوید آن آبجکت دقیقا چه میتواند بکند
مثلا ما میتونیم ابسترکت کلاسی برای پرنده ها تعریف کنیم
اما همه ی پرنده ها پرواز نمیکنن
و یک اینترفیس Flyable تعریف کنیم فقط آنهایی که قابلیت پرواز دارند آن را پیاده سازی کنند .
به این جمله ی کلیدی توجه کنید :
اینترفیس نمیتواند توضیح دهد که دوبرمن نوعی سگ است .. تنها میتواند توضیح دهد که دوبرمن میتواند راه رود (یا مثلا هنگام مواجه با دشمن ,او را گاز گیرد )
برای اینکه بگوییم دوبرمن نوعی سگ است ناچار به تعریف کلاس پدر برای آن هستیم