آموزش برنامه نویسی جاوا (بخش بیست و دوم: وراثت در جاوا)

استاندارد

در بخش قبل در مورد وراثت و مفاهیم آن توضیح داده شد.

یک کلاس پدر و یک کلاس فرزند را تعریف کردیم. و دیدیم که کلاس فرزند می توانست متغیرها و متدهای کلاس پدر را به ارث ببرد.

در این بخش و بخش آینده بیشتر با مفاهیم وراثت کار خواهیم کرد. این بخش بیشتر به نقش Modifier ها در وراثت می پردازیم.

ابتدا دوباره توضیحی مختصر در مورد وراثت می دهیم.

توارث شباهت بین دو کلاس را با استفاده از مفاهیم کلاس پایه (base) و کلاس مشتق شده (derived) بیان می کند.

در بخش قبلی به این دو کلاس، کلاس پدر و فرزند نیز گفته می شود. می توان به کلاس پایه، سوپر کلاس و به کلاس مشتق شده، ساب کلاس (Subclass) نیز گفت.

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

کلاس پایه شامل کلیه خواص و رفتارهائی است که بین کلاس های مشتق شده مشترک است.

در واقع کلاس مشتق شده یا فرزند نوعی از کلاس پایه یا پدر است.

در بخش قبلی در مورد کلاس های اشکال هندسی توضیح داده شد. کلاس پدر، کلاس اشکال هندسی (Shape) و دو کلاس فرزند، کلاس های مستطیل (Rectangle) و کلاس دایره (Circle) می باشند.

هر متغیری که در کلاس Shape تعریف شود، انگار در کلاس های مستطیل و دایره نیز تعریف می شود. حال این دو کلاس نیز می توانند، متغیرها و متدهای خود را تعریف نمایند.

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

وراثت و Modifier ها

می خواهیم نقش Modifier ها را در وراثت بررسی کنیم.

فرض کنید کد زیر که در بخش قبل نیز تعریف شد را دوباره تعریف کنیم.

کد زیر کلاس های عکس بالا را نشان می دهد.

این کد، کلاس Shape را تعریف کرده و سپس کلاس Circle را نیز به صورتی که از کلاس Shape به ارث ببرد تعریف می کند.

مشاهده می کنید که در قسمت Main ، ما یک شی از کلاس Circle ساخته ایم و این شی می تواند به اعضای کلاس پدر و اعضای کلاس Circle دسترسی داشته باشد.

public class JavaApplication1 {

static class Shape{
    String Color;
    int Area;

}
static class Circle extends Shape{
    int Radius;   
}

    public static void main(String[] args) {

        Circle MyCircle = new Circle();
        MyCircle.Color="Red";
        MyCircle.Area=113;
        MyCircle.Radius=6;
    } 
}

مشاهده می کنید که در قسمت Main ، ما یک شی از کلاس Circle ساخته ایم و این شی می تواند به اعضای کلاس پدر و اعضای کلاس Circle دسترسی داشته باشد.

می خواهیم نقش سه Modifier که Public و Private و Protected هستند را در ارث بری، بررسی کنیم.

همان طور که قبلا گفته شد، Public یعنی دسترسی در همه جا. پس کلاس فرزند هم جز همه جا هست. پس هر متغیری که در کلاس پدر به صورت Public تعریف شود، در کلاس فرزند نیز به ارث برده می شود.

برای بررسی دو مورد بعدی، کلاس Shape را به صورت زیر تغییر دهید:

static class Shape{
    private String Color;
    protected int Area; 
}

متغیر اول یعنی Color به صورت private تعریف شده است.

اگر به خط

MyCircle.Color="Red";

در کامپایلر مراجعه کنید، متوجه می شوید که اشکال گرفته است. یعنی متغیر Color دیکر در کلاس فرزند (Circle) قابل دسترس نیست.

در توارث خصوصی کلاس مشتق شده کلیه اعضای کلاس پایه را دارا خواهد بود اما به صورت مخفی و اعضای عمومی کلاس پایه اعضای خصوصی کلاس مشتق شده خواهند شد.

بنابراین یک شی به عنوان یک نمونه از کلاس نمی تواند به اعضای کلاس پایه دسترسی پیدا کند.

پس بهتر است متغیر و یا متدی که نمیخواهید در شی ای از کلاس فرزند به ارث برده شود ، به صورت Private تعریف نمایید.

نکته: توارث خصوصی برای پنهان کردن لایه زیرین پیاده سازی کلاس پایه مفید است.
نکته: در توارث خصوصی کلیه اعضای عمومی کلاس پایه خصوصی می شوند. اگر می خواهید عضوی قابل رویت شود کافی است نام آن را (بدون آرگومان و مقدار برگشتی) در بخش public کلاس مشتق شده ذکر کنید.

با ذکر کلمه protected قبل از متغیر و متد ها در کلاس پایه، به توارث محافظت شده می رسیم.

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

کلمه protected می گوید که اعضای محافظت شده برای هر کسی که از این کلاس ارث می برد قابل دسترس است و برای بقیه خصوصی است.

نقش modifierه Protected نیز در ارث بری مشخص می شود. زیرا متغیر و یا متدی که به صورت protected تعریف شوند، فقط در کلاس فرزند قابل دسترس خواهند بود.

پس در اینجا، متغیر Area فقط در کلاس Shape و کلاس Circle به ارث برده می شود.

این کار یک راهکار امنیتی در برنامه نویسی است.

نکته: در کلیه حالات اعضای خصوصی کلاس پایه در وراثت شرکت نمی کنند و خصوصی باقی می مانند.

نکته: معمولا توارث عمومی است تا رابط کلاس پایه همچنان رابط کلاس مشتق شده باشد.

نکته: توارث محافظت شده خیلی استفاده نمی شود و فقط برای تکمیل زبان برنامه نویسی است.

نکته: مناسب ترین روش این است که اعضای داده ای کلاس را صورت خصوصی تعریف کنید تا امکان تغییر پیاده سازی زیرین حفظ شود.

سپس به وارثین کلاس مجوز دسترسی کنترل شده ای به توابع عضو محافظت شده بدهید.

برای این که مثالی عملی ببینید، کد بالا را خط به خط با چیزهایی که گفته شد بررسی می کنیم:

public class JavaApplication1 {
// تعریف کلاس اشکال هندسی که در اینجا کلاس  پایه است
static class Shape{
    private String Color; // این متغیر فقط در همین کلاس و متدهای همین کلاس قابل دسترس است
    protected int Area; // این متغیرمحافظت شده است یعنی فقط در کلاس خودش و کلاس فرزند قابل دسترس است
}
// تعریف کلاس دایره که از کلاس پایه به ارث می برد
static class Circle extends Shape{
    int Radius;   // تعریف متغیری در کلاس فرزند
}
   // تابع اصلی برنامه
    public static void main(String[] args) {

        Circle MyCircle = new Circle(); // تعریف یک شی از نوع کلاس فرزند
        MyCircle.Color="Red"; // دسترسی به این متغیر خطا می دهد
        MyCircle.Area=113; // به این متغیر می توان دسترسی داشت
        MyCircle.Radius=6;
    } 
}

آموزش برنامه نویسی جاوا (بخش بیست و یکم: مفاهیم اولیه ارث بری)

استاندارد

مفهوم مهم دیگر در برنامه نویسی Object Oriented (آبجکت محور) مفهوم Inheritance می باشد.

وراثت را یکی از سنگ بناهای برنامه نویسی شی گراست ، زیرا امکان ایجاد طبقه بندیهای سلسله مراتبی را بوجود می آورد.

با استفاده از وراثت ، می توانید یک کلاس عمومی بسازید که ویژگیهای مشترک یک مجموعه اقلام بهم مرتبط را تعریف نماید.

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

در جاوا ، کلاسی که به ارث برده می شود را سوپر کلاس (SuperClass) و یا پدر می نامند.

کلاسی که عمل ارث بری را انجام داده و ارث برده است را زیر کلاس (SubClass) و یا فرزند می نامند.

زیر کلاس ، کلیه متغیرهای نمونه و روشهای توصیف شده توسط کلاس بالا را به ارث برده و منحصر بفرد خود را نیز اضافه می کند.

چگونه روابط ارث بری را در برنامه نویسی تشخیص دهیم؟

در واقع بین کلاس ها ممکن است روابطی وجود داشته باشد.

1- مانند is a part of که به معنی قسمتی است از … می باشد.

در این مورد، یک کلاس قسمتی از کلاس دیگر است. مثلا چرخ قسمتی از ماشین است. پس کلاس چرخ قسمتی از کلاس ماشین می شود.

2- روابطی مانند has knowlege of که یعنی اطلاع داشتن، مثلا یک کلاس ممکن است به صورتی حتی غیر مستقیم از کلاس دیگر اطلاع داشته باشد ولی عضوی از آن نباشد.

3- رابطه ی وراثت که موضوع مورد بحث ما است. یعنی یک کلاس فرزند، نوعی از کلاس پدر باشد.

مثلا یک ماشین نوعی از وسیله ی نقلیه است.

یک روباه یک نوع حیوان است.

یک پسر یک نوع انسان است.

یک مستطیل یک نوع از اشکال هندسی است.

Inheritance نيز به مانند بسیاری از اصولا Object Oriented از دنياي واقعي الگو برداري شده است و کاملا قابل درك مي باشد.

مبانی وراثت

فرض کنید بخواهیم یک کلاس کلی به نام Shape را تعریف کنیم. دو کلاس Triangle و Circle از کلاس Shape به صورت شکل زیر ارث می برند.

در کلاس Shape ، دو متغیر Color و Area وجود دارد.

این دو متغیر عینا در کلاس های Triangle و Circle نیز به ارث برده می شوند. یعنی انگار آن ها هم این متغیرها در خود تعریف کرده باشند. ارث بری کار را ساده می کند، زیرا از آنجایی که دو متغیر Color و Area که رنگ و مساحت هستند در همه اشکال وجود دارند.

پس نیازی به تعریف آن ها در همه ی کلاس ها نیست.

به جای این کار یک کلاس کلی Shape تعریف می کنیم و سپس کلاس های Triangle و Circle را طوری تعریف می کنیم که از کلاس Shape به ارث برده شوند.

حال این دو کلاس نیز هر کدام متغیرها و متدهایی را می توانند برای خود تعریف کنند.

در کدهای برنامه نویسی جاوا چگونه عمل می کنیم؟

برای ارث بردن از یک کلاس ، خیلی ساده کافیست تعریف یک کلاس را با استفاده از واژه کلیدی extends در کلاس دیگری قرار دهید.

به کد مثال زیر دقت نمایید:

public class JavaApplication1 {

static class Shape{
    String Color;
    int Area;

}
static class Circle extends Shape{
    int Radius;   
}

    public static void main(String[] args) {

        Circle MyCircle = new Circle();
        MyCircle.Color="Red";
        MyCircle.Area=113;
        MyCircle.Radius=6;
    } 
}

همان طور که مشاهده می کنید، شی MyCircle یک شی از کلاس Circle است.

کلاس Circle خود، دارای متغیر Radius است. این کلاس از کلاس Shape به عنوان پدر خود، ارث بری می کند.

حال شی MyCircle می تواند علاوه بر متغیرهای کلاس خود (Circle) و متغیرهای کلاس پدر خود (Shape) دسترسی داشته باشد و آن ها را مقداردهی و از آن ها استفاده نماید.

حتی اگر در کامپایلر NetBeans بعد از متغیر MyCircle نقطه بزنید، می توانید متغیرها و متدهایی که می تواند به آن ها دسترسی داشته باشد را مشاهده کنید:

متغیرهای Area و Color در کلاس Shape تعریف شده بودند.