ہائے! آج ہم جاوا میں ایک اہم تصور کے بارے میں بات کرنے جا رہے ہیں: انٹرفیس۔ یہ لفظ شاید آپ سے واقف ہے۔ مثال کے طور پر، زیادہ تر کمپیوٹر پروگراموں اور گیمز میں انٹرفیس ہوتے ہیں۔ ایک وسیع معنوں میں، انٹرفیس ایک قسم کا 'ریموٹ کنٹرول' ہے جو دو بات چیت کرنے والی جماعتوں کو جوڑتا ہے۔ روزمرہ کی زندگی میں انٹرفیس کی ایک سادہ مثال ٹی وی ریموٹ کنٹرول ہے۔ یہ دو آبجیکٹ — ایک شخص اور ایک ٹی وی — کو جوڑتا ہے اور مختلف کام انجام دیتا ہے: والیوم کو اوپر یا کم کرنا، چینلز سوئچ کرنا، اور TV کو آن یا آف کرنا۔ ایک فریق (شخص) کو انٹرفیس تک رسائی حاصل کرنے کی ضرورت ہے (ریموٹ کنٹرول پر ایک بٹن دبائیں) تاکہ دوسری پارٹی کو کارروائی انجام دے سکے۔ مثال کے طور پر، ٹی وی کو اگلے چینل میں تبدیل کرنا۔ مزید یہ کہ صارف کو یہ جاننے کی ضرورت نہیں ہے کہ ٹی وی کو کس طرح منظم کیا جاتا ہے یا چینل کی تبدیلی کے عمل کو اندرونی طور پر کیسے نافذ کیا جاتا ہے۔ صرف ایک ہی چیز جس تک صارف کو رسائی حاصل ہے وہ ہے انٹرفیس۔ بنیادی مقصد مطلوبہ نتیجہ حاصل کرنا ہے۔ اس کا پروگرامنگ اور جاوا سے کیا تعلق ہے؟ سب کچھ :) ایک انٹرفیس بنانا ایک باقاعدہ کلاس بنانے کے مترادف ہے، لیکن کلاس کا لفظ استعمال کرنے کے بجائے ، ہم لفظ انٹرفیس کی نشاندہی کرتے ہیں ۔ آئیے سادہ ترین جاوا انٹرفیس دیکھیں، دیکھیں کہ یہ کیسے کام کرتا ہے، اور ہمیں اس کی ضرورت کیوں پڑے گی:
آپ نے
public interface CanSwim {
public void swim();
}
ہم نے ایک CanSwim انٹرفیس بنایا ہے۔ یہ تھوڑا سا ہمارے ریموٹ کنٹرول کی طرح ہے، لیکن ایک 'بٹن' کے ساتھ: swim() طریقہ۔ لیکن ہم اس ریموٹ کنٹرولر کو کیسے استعمال کرتے ہیں؟ ایسا کرنے کے لیے، ہمیں ایک طریقہ کو نافذ کرنے کی ضرورت ہے، یعنی ہمارا ریموٹ کنٹرول بٹن۔ انٹرفیس استعمال کرنے کے لیے، ہمارے پروگرام میں کچھ کلاسوں کو اس کے طریقوں کو نافذ کرنا ہوگا۔ آئیے ایک ایسی کلاس ایجاد کریں جس کی اشیاء 'تیر سکتی ہیں'۔ مثال کے طور پر، ایک بتھ کلاس فٹ بیٹھتی ہے:
public class Duck implements CanSwim {
public void swim() {
System.out.println("Duck, swim!");
}
public static void main(String[] args) {
Duck duck = new Duck();
duck.swim();
}
}
"ہم یہاں کیا دیکھتے ہیں؟ Duck کلاس کو CanSwim انٹرفیس کے ساتھ امپلیمینٹس کی ورڈ کے ذریعے 'وابستہ' کیا گیا ہے ۔ آپ کو یاد ہوگا کہ ہم نے وراثت کے ذریعے دو کلاسوں کو جوڑنے کے لیے ایک جیسا طریقہ کار استعمال کیا تھا، لیکن اس صورت میں ہم نے توسیع کا لفظ استعمال کیا۔ مکمل وضاحت کے ساتھ، ہم ' پبلک کلاس ڈک امپلیمنٹس کین سوئم ' کا لفظی ترجمہ کر سکتے ہیں: 'عوامی بتھ کلاس CanSwim انٹرفیس کو نافذ کرتی ہے'۔ اس کا مطلب ہے کہ انٹرفیس سے وابستہ کلاس کو اپنے تمام طریقوں کو لاگو کرنا چاہیے۔ نوٹ: ہماری Duck
کلاس، بالکل اسی طرح انٹرفیس CanSwim
کا ایک swim()
طریقہ ہے، اور اس میں کچھ منطق ہے، یہ ایک لازمی ضرورت ہے۔ اگر ہم کلاس میں کوئی طریقہ public class Duck implements CanSwim
بنائے بغیر لکھتے ہیں، تو کمپائلر ہمیں ایک غلطی دے گا: بطخ تجریدی نہیں ہے اور تجریدی طریقہ سوئم کو اوور رائڈ نہیں کرتا ہے۔ () CanSwim میں کیوں؟ ایسا کیوں ہوتا ہے؟ اگر ہم ٹی وی کی مثال کے ذریعے غلطی کی وضاحت کرتے ہیں، تو یہ ایسا ہی ہوگا جیسے کسی کو ٹی وی کا ریموٹ کنٹرول ایک 'چینل تبدیل کریں' کے بٹن کے ساتھ دینا جو چینلز کو تبدیل نہیں کر سکتا۔ آپ بٹن دبا سکتے ہیں۔ جتنا آپ چاہیں، لیکن یہ کام نہیں کرے گا۔ ریموٹ کنٹرول خود سے چینلز کو تبدیل نہیں کرتا ہے: یہ صرف ٹی وی کو سگنل بھیجتا ہے، جو چینل کی تبدیلی کے پیچیدہ عمل کو نافذ کرتا ہے۔ اور اسی طرح یہ ہماری بطخ کے ساتھ ہے: اسے تیراکی کا طریقہ معلوم ہونا چاہیے تاکہ اسے انٹرفیس کا استعمال کرتے ہوئے کہا جا سکے ۔ اگر یہ نہیں جانتا ہے کہ کیسے، انٹرفیس دو فریقوں - شخص اور پروگرام کو جوڑتا نہیں ہے۔ وہ شخص پروگرام کے اندر تیرنے کا طریقہ استعمال نہیں کر سکے گا ۔ اب آپ زیادہ واضح طور پر سمجھ گئے ہیں کہ انٹرفیس کس کے لیے ہیں۔ ایک انٹرفیس اس طرز عمل کی وضاحت کرتا ہے جو انٹرفیس کو نافذ کرنے والی کلاسوں کا ہونا ضروری ہے۔ 'رویہ' طریقوں کا مجموعہ ہے۔ اگر ہم کئی میسنجر بنانا چاہتے ہیں تو سب سے آسان کام انٹرفیس بنانا ہے۔ ہر رسول کو کیا ضرورت ہے؟ بنیادی سطح پر، انہیں پیغامات وصول کرنے اور بھیجنے کے قابل ہونا چاہیے۔ swim()
Duck
CanSwim
CanSwim
swim()
Duck
Messenger
public interface Messenger{
public void sendMessage();
public void getMessage();
}
اب ہم آسانی سے اپنی میسنجر کلاسز بنا سکتے ہیں جو متعلقہ انٹرفیس کو نافذ کرتی ہیں۔ مرتب کرنے والا خود ہمیں اپنی کلاسوں میں ان کو لاگو کرنے پر مجبور کرے گا۔ ٹیلی گرام:
public class Telegram implements Messenger {
public void sendMessage() {
System.out.println("Sending a Telegram message!");
}
public void getMessage() {
System.out.println("Receiving a Telegram message!");
}
}
واٹس ایپ:
public class WhatsApp implements Messenger {
public void sendMessage() {
System.out.println("Sending a WhatsApp message!");
}
public void getMessage() {
System.out.println("Reading a WhatsApp message!");
}
}
وائبر:
public class Viber implements Messenger {
public void sendMessage() {
System.out.println("Sending a Viber message!");
}
public void getMessage() {
System.out.println("Receiving a Viber message!");
}
}
یہ کیا فوائد فراہم کرتا ہے؟ ان میں سب سے اہم ڈھیلا جوڑا ہے۔ تصور کریں کہ ہم ایک ایسا پروگرام ڈیزائن کر رہے ہیں جو کلائنٹ کا ڈیٹا اکٹھا کرے گا۔ کلاس Client
کو یقینی طور پر ایک فیلڈ کی ضرورت ہوتی ہے جس کی نشاندہی کرنے کے لیے کلائنٹ کون سا مخصوص میسنجر استعمال کر رہا ہے۔ انٹرفیس کے بغیر، یہ عجیب لگے گا:
public class Client {
private WhatsApp whatsApp;
private Telegram telegram;
private Viber viber;
}
ہم نے تین فیلڈز بنائے ہیں، لیکن ایک کلائنٹ کے پاس صرف ایک میسنجر ہو سکتا ہے۔ ہم صرف یہ نہیں جانتے کہ کون سا۔ لہذا ہمیں کلائنٹ کے ساتھ بات چیت کرنے کے قابل ہونے کے لئے کلاس میں ہر امکان کو شامل کرنا ہوگا۔ یہ پتہ چلتا ہے کہ ان میں سے ایک یا دو ہمیشہ رہیں گے null
، پروگرام کے لیے مکمل طور پر غیر ضروری۔ اس کے بجائے ہمارا انٹرفیس استعمال کرنا بہتر ہے:
public class Client {
private Messenger messenger;
}
یہ ڈھیلے جوڑے کی ایک مثال ہے! کلاس میں ایک مخصوص میسنجر کلاس کی وضاحت کرنے کے بجائے Client
، ہم صرف یہ بتاتے ہیں کہ کلائنٹ کے پاس میسنجر ہے۔ پروگرام کے چلنے کے دوران کس کا قطعی طور پر تعین کیا جائے گا۔ لیکن ہمیں اس کے لیے انٹرفیس کی ضرورت کیوں ہے؟ انہیں زبان میں بھی کیوں شامل کیا گیا؟ یہ ایک اچھا سوال ہے - اور صحیح سوال! کیا ہم عام وراثت کا استعمال کرتے ہوئے وہی نتیجہ حاصل نہیں کر سکتے؟ کلاس Messenger
بطور والدین، اور Viber
, Telegram
اور WhatsApp
بچوں کے طور پر۔ درحقیقت، یہ ممکن ہے۔ لیکن اس میں ایک رکاوٹ ہے۔ جیسا کہ آپ پہلے ہی جانتے ہیں، جاوا کی کوئی کثیر وراثت نہیں ہے۔ لیکن ایک سے زیادہ انٹرفیس کے لیے سپورٹ موجود ہے۔ ایک کلاس آپ جتنے چاہیں انٹرفیس نافذ کر سکتی ہے۔ تصور کریں کہ ہمارے پاس ایک Smartphone
کلاس ہے جس میں ایک App
فیلڈ ہے، جو اسمارٹ فون پر انسٹال کردہ ایپ کی نمائندگی کرتا ہے۔
public class Smartphone {
private App app;
}
یقینا، ایک ایپ اور میسنجر ایک جیسے ہیں، لیکن وہ اب بھی مختلف چیزیں ہیں۔ میسنجر کے موبائل اور ڈیسک ٹاپ ورژن ہوسکتے ہیں، لیکن ایپ خاص طور پر موبائل ایپ کی نمائندگی کرتی ہے۔ یہاں معاہدہ ہے - اگر ہم وراثت کا استعمال کرتے ہیں، تو ہم کلاس Telegram
میں کوئی چیز شامل نہیں کر پائیں گے۔ Smartphone
سب کے بعد، Telegram
کلاس بیک وقت وراثت نہیں بن سکتی App
اور Messenger
! اور ہم نے اسے پہلے ہی وراثت Messenger
میں شامل کر لیا ہے Client
۔ لیکن Telegram
کلاس آسانی سے دونوں انٹرفیس کو نافذ کر سکتی ہے! اس کے مطابق، ہم Client
کلاس کو Telegram
بطور ایک آبجیکٹ دے سکتے ہیں Messenger
، اور ہم اسے Smartphone
کلاس کو بطور ایک دے سکتے ہیں App
۔ یہاں یہ ہے کہ آپ اسے کیسے کرتے ہیں:
public class Telegram implements Application, Messenger {
// ...methods
}
public class Client {
private Messenger messenger;
public Client() {
this.messenger = new Telegram();
}
}
public class Smartphone {
private Application application;
public Smartphone() {
this.application = new Telegram();
}
}
اب ہم Telegram
کلاس کا استعمال کر رہے ہیں جس طرح ہم چاہتے ہیں۔ کچھ جگہوں پر، یہ ایک کے طور پر کام کرتا ہے App
۔ دوسری جگہوں پر، یہ ایک کے طور پر کام کرتا ہے Messenger
۔ آپ نے یقینی طور پر پہلے ہی محسوس کیا ہے کہ انٹرفیس کے طریقے ہمیشہ 'خالی' ہوتے ہیں، یعنی ان کا کوئی نفاذ نہیں ہوتا ہے۔ اس کی وجہ سادہ ہے: انٹرفیس رویے کی وضاحت کرتا ہے، لیکن یہ اس پر عمل درآمد نہیں کرتا ہے۔ 'انٹرفیس کو نافذ کرنے والی تمام اشیاء کو CanSwim
تیرنے کے قابل ہونا چاہیے': انٹرفیس ہمیں اتنا ہی بتاتا ہے۔ مچھلی، بطخ اور گھوڑوں کے تیرنے کا مخصوص طریقہ , Fish
اور Duck
کلاسز کے لیے ایک سوال ہے Horse
، نہ کہ انٹرفیس۔ جیسے چینل بدلنا ٹی وی کا کام ہے۔ ریموٹ آپ کو اس کے لیے ایک بٹن دیتا ہے۔ تاہم، جاوا 8 - پہلے سے طے شدہ طریقوں میں ایک دلچسپ اضافہ ظاہر ہوا۔ مثال کے طور پر، آپ کے انٹرفیس میں 10 طریقے ہیں۔ ان میں سے 9 کے مختلف کلاسوں میں مختلف نفاذ ہیں، لیکن ایک سب کے لیے ایک جیسا ہے۔ اس سے پہلے، جاوا 8 سے پہلے، انٹرفیس کے طریقوں پر کوئی عمل درآمد نہیں ہوتا تھا: مرتب کرنے والے نے فوری طور پر ایک غلطی دی تھی۔ اب آپ کچھ ایسا کر سکتے ہیں:
public interface CanSwim {
public default void swim() {
System.out.println("Swim!");
}
public void eat();
public void run();
}
مطلوبہ الفاظ کا استعمال کرتے ہوئے default
، ہم نے پہلے سے طے شدہ نفاذ کے ساتھ ایک انٹرفیس طریقہ بنایا ہے۔ ہمیں دو دیگر طریقوں کے لیے خود اپنا نفاذ فراہم کرنے کی ضرورت ہے — eat()
اور run()
— ان تمام کلاسوں میں جو لاگو کرتے ہیں CanSwim
۔ ہمیں طریقہ کار کے ساتھ ایسا کرنے کی ضرورت نہیں ہے swim()
: نفاذ ہر کلاس میں ایک جیسا ہوگا۔ ویسے، آپ ماضی کے کاموں میں انٹرفیس سے پہلے ہی آ چکے ہیں، چاہے آپ نے نوٹس نہ کیا ہو :) یہاں ایک واضح مثال ہے: ![جاوا میں انٹرفیس کیوں ضروری ہیں - 2](https://cdn.codegym.cc/images/article/e0c3daf6-4bf5-4f82-afda-421dbe90d1c3/1024.jpeg)
List
اور Set
انٹرفیس کے ساتھ کام کیا ہے! مزید واضح طور پر، آپ نے ان کے نفاذ کے ساتھ کام کیا ہے — ArrayList
, LinkedList
, HashSet
, وغیرہ۔ وہی خاکہ واضح طور پر ایک مثال دیتا ہے جہاں ایک کلاس ایک ہی وقت میں متعدد انٹرفیس کو نافذ کرتی ہے۔ مثال کے طور پر، اور (ڈبل اینڈڈ قطار) انٹرفیس کو LinkedList
لاگو کرتا ہے ۔ آپ انٹرفیس سے واقف ہیں ، یا اس کے نفاذ سے ۔ ویسے، یہ خاکہ ایک خصوصیت کی وضاحت کرتا ہے: انٹرفیس دوسرے انٹرفیس کے وارث ہوسکتے ہیں۔ انٹرفیس وراثت میں ملتا ہے ، جبکہ وراثت میں ملتا ہے ۔ یہ ضروری ہے اگر آپ انٹرفیس کے درمیان تعلق کو ظاہر کرنا چاہتے ہیں، جہاں ایک انٹرفیس دوسرے کا توسیعی ورژن ہے۔ آئیے انٹرفیس کے ساتھ ایک مثال پر غور کریں۔ ہم نے ابھی تک جائزہ نہیں لیا ہے ، لیکن یہ کافی آسان ہے اور اسٹور پر ایک عام قطار، یا لائن کی طرح کام کرتا ہے۔ آپ صرف قطار کے آخر میں آئٹمز شامل کر سکتے ہیں، اور انہیں صرف شروع سے لے سکتے ہیں۔ کسی وقت، ڈویلپرز کو قطار کے ایک بہتر ورژن کی ضرورت ہوتی ہے تاکہ دونوں سروں پر اشیاء کو شامل کیا جا سکے۔ لہذا انہوں نے ایک انٹرفیس بنایا، جو کہ ایک دوہری قطار ہے۔ اس میں ایک عام قطار کے تمام طریقے ہیں۔ سب کے بعد، یہ ڈبل ختم ہونے والی قطار کا پیرنٹ ہے، لیکن اس میں نئے طریقے بھی شامل کیے گئے ہیں۔List
Deque
Map
HashMap
SortedMap
Map
Deque
Queue
Queue
Queues
Deque
GO TO FULL VERSION