اینترفیس و کاربرد آن در زبان جاوا به زبان ساده و همراه با مثال

نویسنده : سید ایوب کوکبی ۲۳ فروردین ۱۳۹۸

اینترفیس و کاربرد آن در زبان جاوا به زبان ساده و همراه با مثال

اینترفیس یکی از مهم‌ترین مباحث برنامه‌نویسی شیءگرا (OOP) است که در این پست قصد داریم کاربرد آن را به زبان ساده توضیح دهیم و مهم‌تر از آن فهم اینکه در نبودش چه سختی‌هایی را متحمل خواهیم شد. مثال‌ها به زبان جاوا یا اصطلاحاً Pure Java نوشته شده تا به جای درگیر شدن با کدهای فریم‌ورک اندروید روی بحث اصلی تمرکز شود. البته با توجه به اینکه زبان برنامه‌نویسی اندروید جاوا است، مفاهیم آموخته شده را به راحتی می‌توانید در محیط اندروید هم استفاده کنید. مثال و توضیحات این مطلب برگفته از اینجاست که در این پست به زبان فارسی به همراه توضیحات تکمیلی خدمت شما ارائه می‌دهیم.

اینترفیس در جاوا

طرح مسئله

مثالمان را با یک سگ از نژاد پاگ (Pug) آغاز می‌کنیم. یک کلاس Pug درست می‌کنیم:

public class Pug
{
    private String name;

    public Pug(String n)
    {
        name = n;
    }

    public String getName()
    {
        return name;
    }

    public String bark()
    {
        return "Arf!";
    }

    public boolean hasCurlyTail()
    {
        return true;
    }
}

فیلد name نام سگ را ذخیره می‌کند که مقدار آن از طریق سازندۀ کلاس دریافت می‌شود. متد ()getName مقدار این فیلد را برمی‌گرداند. متد ()bark صدای این نژاد بخصوص را شبیه‌سازی می‌کند و نهایتاً ()hasCrulyTail اعلام می‌کند که دم سگ فرخورده است یا نه.

حالا نژاد دیگری از سگ‌ها یعنی لابرادور (Labrador) را در قالب یک کلاس پیاده‌سازی می‌کنیم:

public class Lab
{
    private String name;

    public Lab(String n)
    {
        name = n;
    }

    public String getName()
    {
        return name;
    }

    public String bark()
    {
        return "Woof!";
    }

    public boolean hasCurlyTail()
    {
        return false;
    }
}

اینجا نیز دقیقاً همان کدهای قبلی را داریم با این تفاوت که این نژاد هنگام پارس کردن صدای متفاوتی تولید می‌کنند و دم‌شان فرخورده نیست (به همین دلیل متد آخری مقدار false برمی‌گرداند).

بخوانید  بهینه‌سازی بازیهای اندروید در یونیتی

حالا بیایید از کلاس‌های فوق، دو آبجکت بسازیم:

Pug pug = new Pug("Spot");
Lab lab = new Lab("Fido");

در خط اول، آبجکتی از کلاس پاگ ساخته‌ایم و اسم سگ را Spot گذاشته‌ایم. در خط بعدی سگ دیگری از نژاد لابرادور به نام Fido ساخته‌ایم. حالا می‌توانیم متدها را بر روی هر یک از دو آبجکت فرخوانی کنیم:

pug.bark()           -> "Arf!"
lab.bark()           -> "Woof!"
pug.hasCurlyTail()   -> true
lab.hasCurlyTail()   -> false
pug.getName()        -> "Spot"
lab.getName()        -> "Fido"

اکنون می‌خواهیم قفس نگه‌داری سگ‌ها (Kennel) را هم پیاده‌سازی می‌کنیم. سگ‌های هر نژاد را در آرایه‌ای جدا ذخیره می‌کنیم:

public class Kennel
{
    Pug[] pugs = new Pug[10];
    Lab[] labs = new Lab[10];

    public void addPug(Pug p)
    {
        ...
    }

    public void addLab(Lab l)
    {
        ...
    }

    public void printDogs()
    {
        // Display names of all the dogs
    }
}

همه چیز درست است ولی مشکلی وجود دارد. اگر بخواهیم نژاد دیگری از سگ‌ها به کلاس اضافه کنیم، باید آرایه‌ای جدید بسازیم و متد جدیدی هم برای اضافه کردن آن نژاد اضافه کنیم و حتی در متد ()printDogs آرایۀ جدیدی برای پرینت اضافه کنیم. راه‌حل بهتری وجود دارد که در ادامه خواهیم گفت.

حل مشکل با کمک اینترفیس

وقتی خوب به کدهایی که نوشته‌ایم فکر می‌کنیم. متوجه خواهیم شد که سگ‌ها فارغ نژاد، خصوصیات و رفتار یکسانی دارند. همۀ آن‌ها پارس می‌کنند، اسم دارند و ممکن است دم فرخورده داشته باشند. ما می‌توانیم این ویژگی‌های مشترک را درون یک اینترفیس قرار دهیم و پیاده‌سازی را بر عهدۀ هر نژاد بگذاریم. به این صورت:

public interface Dog
{
    public String bark();
    public String getName();
    public boolean hasCurlyTail();
}

در واقع اینترفیس فوق به زبان ساده می‌گوید: «همۀ سگ‌ها قادر به انجام این کارها هستند.» ولی چیزی دربارۀ چگونگی انجام آن کارها نمی‌گوید.

بخوانید  معنی استاتیک بودن زبان جاوا چیست؟

حال دو کلاس قبلی یعنی Pug و Dog را بازنویسی می‌کنیم طوری که اینترفیس Dog را پیاده‌سازی کنند. در واقع کلاس Pug و Lab با پیاده‌سازی اینترفیس فوق بیان می‌کنند که یک Dog هستند. به زبان انگلیسی Pug is Dog و Lab is Dog:

public class Pug implements Dog
{
    // the rest is the same as before
}

public class Lab implements Dog
{
    // the rest is the same as before
}

هیچ چیزی فرق نکرده است. همانند گذشته می‌توانید از کلاس‌های فوق اشیاء جدیدی بسازید البته با این تفاوت که در سمت چپ اینترفیس Dog را داریم و سمت راست، کلاس خاصی از آن اینترفیس. مثلاً در کد پایین d1 یک Dog بوده ولی به صورت بخصوصی از نژاد Pug است:

Dog d1 = new Pug("Spot");
Dog d2 = new Lab("Fido");

برای فرخوانی متدها نیز به این شکل عمل می‌کنیم:

d1.bark()           -> "Arf!"
d2.bark()           -> "Woof!"
d1.hasCurlyTail()   -> true
d2.hasCurlyTail()   -> false
d1.getName()        -> "Spot"
d2.getName()        -> "Fido"

نکتۀ جالب اینجاست که اینترفیس، نوع آبجکت را نگه‌داری می‌کند و به همین خاطر هنگام فراخوانی متد ()bark تشخیص می‌دهد کدام پیاده‌سازی را فرخوانی کند. شما به راحتی می‌توانید d1 را با کلاس دیگری مثلاً از نژاد پودل جایگزین کنید و صدای پارس آن را در خروجی ببینید.

با وجود اینترفیس، کلاس Kennel هم بسیار ساده و جمع‌وجور می‌شود. فقط یک آرایه و یک متد ()addDog نیاز داریم.  مابقی کار بر عهدۀ کلاس‌هایی است که این اینترفیس را پیاده‌سازی می‌کنند. اگر از اینترفیس استفاده نمی‌کردیم به ازای هر نژاد جدید باید تغییراتی در کلاس Kennel اعمال می‌کردیم.

public class Kennel 
{
    Dog[] dogs = new Dog[20];

    public void addDog(Dog d)
    {
        ...
    }

    public void printDogs()
    {
        // Display names of all the dogs
    }
 }

این هم طرز استفاده از کلاس Kennel:

Kennel k = new Kennel();
 Dog d1 = new Pug("Spot");
 Dog d2 = new Lab("Fido");
 k.addDog(d1);
 k.addDog(d2);
 k.printDogs();

و خروجی نهایی:

Spot
 Fido

در واقع اینترفیس به شما این اجازه را می‌دهد تا یک سری رفتار مشخص را بین کلاس‌هایی که آن را پیاده‌سازی می‌کنند به اشتراک بگذارند. وقتی می‌گوییم فلان کلاس، اینترفیس Dog را پیاده‌سازی کرده، مطمئن هستم که حاوی متد ()bark است. با کمک اینترفیس‌ها می‌توان آرایه‌هایی یا کالکشن‌هایی داشته باشیم که از ماهیت اشیاء داخلشان خبر ندارند و صرفاً می‌دانند اشیاء ذخیره شده چه کارهایی می‌توانند انجام دهند. مابقی جزئیات را فقط اشیائی که آن اینترفیس را پیاده‌سازی کرده‌اند می‌دانند.

بخوانید  انتشار برنامه اندروید مثل یک حرفه‌ای

در زبان‌های شی‌گرا مثل جاوا و سی‌شارپ، اینترفیس جایگاه ویژه‌ای دارد طوری که در اغلب الگوهای طراحی و معماری به کار می‌رود. داخل  خودِ Android SDK کلی اینترفیس هست که شاید تا الان در کدهایتان استفاده می‌کردید ولی از وجودشان مطلع نبودید. با توضیحاتی که دادیم امیدواریم به ضرورت اینترفیس‌ها پی برده باشید و در برنامه‌های آتی خود استفاده کنید.

سید ایوب کوکبی

نویسنده و مترجم...

0 دیدگاه

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