-
ایک انٹرفیس صرف رویے کی وضاحت کرتا ہے۔ اس کی کوئی ریاست نہیں ہے۔ لیکن ایک تجریدی کلاس میں ریاست شامل ہے: یہ دونوں کو بیان کرتا ہے۔
Bird
مثال کے طور پر، خلاصہ کلاس اور انٹرفیس لیںCanFly
:public abstract class Bird { private String species; private int age; public abstract void fly(); public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
آئیے
MockingJay
برڈ کلاس بنائیں اور اسے وارث بنائیںBird
:public class MockingJay extends Bird { @Override public void fly() { System.out.println("Fly, bird!"); } public static void main(String[] args) { MockingJay someBird = new MockingJay(); someBird.setAge(19); System.out.println(someBird.getAge()); } }
جیسا کہ آپ دیکھ سکتے ہیں، ہم آسانی سے خلاصہ کلاس کی حالت - اس
species
اورage
متغیر تک رسائی حاصل کر سکتے ہیں۔لیکن اگر ہم ایک انٹرفیس کے ساتھ ایسا کرنے کی کوشش کرتے ہیں، تو تصویر مختلف ہے. ہم اس میں متغیرات شامل کرنے کی کوشش کر سکتے ہیں:
public interface CanFly { String species = new String(); int age = 10; public void fly(); } public interface CanFly { private String species = new String(); // Error private int age = 10; // Another error public void fly(); }
ہم انٹرفیس کے اندر نجی متغیرات کا اعلان بھی نہیں کر سکتے ۔ کیوں؟ کیونکہ پرائیویٹ موڈیفائر صارف سے نفاذ کو چھپانے کے لیے بنایا گیا تھا۔ اور ایک انٹرفیس کے اندر کوئی عمل درآمد نہیں ہے: چھپانے کے لیے کچھ بھی نہیں ہے۔
ایک انٹرفیس صرف رویے کی وضاحت کرتا ہے۔ اس کے مطابق، ہم انٹرفیس کے اندر گیٹرز اور سیٹرز کو لاگو نہیں کر سکتے۔ یہ انٹرفیس کی نوعیت ہے: انہیں رویے کے ساتھ کام کرنے کی ضرورت ہے، ریاست کے ساتھ نہیں۔
جاوا 8 نے ان انٹرفیس کے لیے پہلے سے طے شدہ طریقے متعارف کرائے جن پر عمل درآمد ہوتا ہے۔ آپ ان کے بارے میں پہلے ہی جانتے ہیں، لہذا ہم خود کو نہیں دہرائیں گے۔
-
ایک تجریدی کلاس ان کلاسوں کو جوڑتی اور متحد کرتی ہے جو بہت قریب سے وابستہ ہیں۔ ایک ہی وقت میں، ایک ہی انٹرفیس کو کلاسوں کے ذریعہ لاگو کیا جاسکتا ہے جن میں بالکل مشترک نہیں ہے۔
آئیے پرندوں کے ساتھ اپنی مثال پر واپس آتے ہیں۔
Bird
اس طبقے پر مبنی پرندے بنانے کے لیے ہماری تجریدی کلاس کی ضرورت ہے۔ بس پرندے اور کچھ نہیں! یقیناً پرندے مختلف قسم کے ہوں گے۔انٹرفیس کے ساتھ
CanFly
، ہر کوئی اپنے طریقے سے آگے بڑھتا ہے۔ یہ صرف اس کے نام سے وابستہ رویے (پرواز) کو بیان کرتا ہے۔ بہت سی غیر متعلقہ چیزیں 'اڑ سکتی ہیں'۔یہ 4 ادارے ایک دوسرے سے متعلق نہیں ہیں۔ وہ سب زندہ بھی نہیں ہیں۔ تاہم، وہ سب
CanFly
.ہم تجریدی کلاس کا استعمال کرتے ہوئے ان کی وضاحت نہیں کر سکے۔ وہ ایک جیسی ریاست یا ایک جیسی فیلڈز کا اشتراک نہیں کرتے ہیں۔ ہوائی جہاز کی وضاحت کرنے کے لیے، ہمیں شاید ماڈل، پیداواری سال، اور مسافروں کی زیادہ سے زیادہ تعداد کے لیے فیلڈز کی ضرورت ہوگی۔ کارلسن کے لیے، ہمیں ان تمام مٹھائیوں کے لیے کھیتوں کی ضرورت ہوگی جو اس نے آج کھائی ہیں، اور ان کھیلوں کی فہرست جو وہ اپنے چھوٹے بھائی کے ساتھ کھیلے گا۔ ایک مچھر کے لیے، ...اوہ... مجھے یہ تک نہیں معلوم... ہو سکتا ہے، 'جھنجھلاہٹ کی سطح'؟ :)
نقطہ یہ ہے کہ ہم ان کو بیان کرنے کے لیے تجریدی کلاس کا استعمال نہیں کر سکتے۔ وہ بہت مختلف ہیں۔ لیکن ان کا مشترکہ برتاؤ ہے: وہ اڑ سکتے ہیں۔ ایک انٹرفیس دنیا کی ہر اس چیز کو بیان کرنے کے لیے بہترین ہے جو اڑنے، تیرنے، چھلانگ لگانے یا کسی اور طرز عمل کی نمائش کر سکتی ہے۔
-
کلاسز آپ جتنے بھی انٹرفیس چاہیں لاگو کر سکتے ہیں، لیکن وہ صرف ایک کلاس کو وراثت میں لے سکتے ہیں۔
ہم پہلے ہی ایک سے زیادہ بار اس کا ذکر کر چکے ہیں۔ جاوا میں کلاسوں کی متعدد وراثت نہیں ہے، لیکن یہ انٹرفیس کی متعدد وراثت کی حمایت کرتا ہے۔ یہ نکتہ پچھلے ایک کے کچھ حصے کی پیروی کرتا ہے: ایک انٹرفیس بہت سی مختلف کلاسوں کو جوڑتا ہے جن میں اکثر کوئی اور چیز مشترک نہیں ہوتی ہے، جبکہ ایک تجریدی کلاس بہت قریب سے متعلقہ کلاسوں کے گروپ کے لیے بنائی جاتی ہے۔ لہذا، یہ سمجھ میں آتا ہے کہ آپ صرف ایک ایسی کلاس کے وارث ہوسکتے ہیں۔ ایک تجریدی کلاس ایک 'is-a' تعلق کو بیان کرتی ہے۔
معیاری انٹرفیس: ان پٹ اسٹریم اور آؤٹ پٹ اسٹریم
ہم پہلے ہی ان پٹ اور آؤٹ پٹ اسٹریمز کے لیے ذمہ دار مختلف کلاسز پر جا چکے ہیں۔ آئیے غور کریںInputStream
اور OutputStream
. عام طور پر، یہ بالکل بھی انٹرفیس نہیں ہیں، بلکہ مکمل طور پر حقیقی تجریدی کلاسز ہیں۔ اب آپ جانتے ہیں کہ اس کا کیا مطلب ہے، لہذا ان کے ساتھ کام کرنا بہت آسان ہو جائے گا :) InputStream
بائٹ ان پٹ کے لیے ذمہ دار ایک تجریدی کلاس ہے۔ Java کی کئی کلاسیں ہیں جو وراثت میں ملتی ہیں InputStream
۔ ان میں سے ہر ایک کو مختلف ذرائع سے ڈیٹا حاصل کرنے کے لیے ڈیزائن کیا گیا ہے۔ چونکہ InputStream
والدین ہے، یہ کئی طریقے فراہم کرتا ہے جو ڈیٹا اسٹریمز کے ساتھ کام کرنا آسان بناتا ہے۔ ہر اولاد کے InputStream
پاس یہ طریقے ہیں:
int available()
پڑھنے کے لیے دستیاب بائٹس کی تعداد لوٹاتا ہے۔close()
ان پٹ سٹریم کو بند کرتا ہے؛int read()
سٹریم میں اگلے دستیاب بائٹ کی عددی نمائندگی لوٹاتا ہے۔ اگر سلسلہ کا اختتام ہو گیا ہے، تو -1 واپس کر دیا جائے گا؛int read(byte[] buffer)
بفر میں بائٹس کو پڑھنے کی کوشش کرتا ہے، اور پڑھنے والے بائٹس کی تعداد لوٹاتا ہے۔ جب یہ فائل کے آخر تک پہنچ جاتا ہے، تو یہ -1 لوٹتا ہے۔int read(byte[] buffer, int byteOffset, int byteCount)
بائٹس کے بلاک کا حصہ لکھتا ہے۔ یہ اس وقت استعمال ہوتا ہے جب بائٹ سرنی پوری طرح سے بھری نہ ہو۔ جب یہ فائل کے آخر تک پہنچ جاتا ہے، تو یہ -1 لوٹتا ہے۔long skip(long byteCount)
ان پٹ سٹریم میں byteCount بائٹس کو چھوڑ دیتا ہے، اور نظر انداز کیے گئے بائٹس کی تعداد لوٹاتا ہے۔
FileInputStream
: کی سب سے عام قسمInputStream
۔ یہ فائل سے معلومات کو پڑھنے کے لیے استعمال ہوتا ہے۔StringBufferInputStream
: ایک اور مددگار قسمInputStream
۔ یہ ایک تار کو ایک میں تبدیل کرتا ہےInputStream
؛BufferedInputStream
: بفر شدہ ان پٹ سٹریم۔ یہ اکثر کارکردگی کو بڑھانے کے لیے استعمال ہوتا ہے۔
BufferedReader
اور کہا کہ آپ کو اسے استعمال کرنے کی ضرورت نہیں ہے؟ جب ہم لکھتے ہیں:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))
…آپ کو استعمال کرنے کی ضرورت نہیں ہے BufferedReader
: ایک InputStreamReader
کام کر سکتا ہے۔ لیکن BufferedReader
کارکردگی کو بہتر بناتا ہے اور انفرادی حروف کے بجائے ڈیٹا کی پوری لائنوں کو بھی پڑھ سکتا ہے۔ ایک ہی چیز پر لاگو ہوتا ہے BufferedInputStream
! کلاس ان پٹ ڈیوائس تک مسلسل رسائی کیے بغیر ایک خصوصی بفر میں ان پٹ ڈیٹا جمع کرتی ہے۔ آئیے ایک مثال پر غور کریں:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class BufferedInputExample {
public static void main(String[] args) throws Exception {
InputStream inputStream = null;
BufferedInputStream buffer = null;
try {
inputStream = new FileInputStream("D:/Users/UserName/someFile.txt");
buffer = new BufferedInputStream(inputStream);
while(buffer.available()>0) {
char c = (char)buffer.read();
System.out.println("Character read: " + c);
}
} catch(Exception e) {
e.printStackTrace();
} finally {
inputStream.close();
buffer.close();
}
}
}
اس مثال میں، ہم ' D:/Users/UserName/someFile.txt ' پر کمپیوٹر پر موجود فائل سے ڈیٹا پڑھتے ہیں ۔ ہم 2 اشیاء بناتے ہیں - a FileInputStream
اور a BufferedInputStream
جو اسے 'لپٹتے' ہیں۔ پھر ہم فائل سے بائٹس پڑھتے ہیں اور انہیں حروف میں تبدیل کرتے ہیں۔ اور ہم فائل ختم ہونے تک ایسا کرتے ہیں۔ جیسا کہ آپ دیکھ سکتے ہیں، یہاں کچھ بھی پیچیدہ نہیں ہے۔ آپ اس کوڈ کو کاپی کرسکتے ہیں اور اسے اپنے کمپیوٹر پر ایک حقیقی فائل پر چلا سکتے ہیں :) OutputStream
کلاس ایک خلاصہ کلاس ہے جو بائٹس کے آؤٹ پٹ اسٹریم کی نمائندگی کرتی ہے۔ جیسا کہ آپ پہلے ہی جانتے ہیں، یہ ایک کے برعکس ہے InputStream
۔ یہ کہیں سے ڈیٹا پڑھنے کے لیے ذمہ دار نہیں ہے، بلکہ کہیں سے ڈیٹا بھیجنے کے لیے ذمہ دار ہے ۔ جیسے InputStream
، یہ تجریدی کلاس اپنی تمام اولادوں کو آسان طریقوں کا ایک سیٹ فراہم کرتی ہے:
void close()
آؤٹ پٹ سٹریم بند کرتا ہے؛void flush()
تمام آؤٹ پٹ بفرز کو صاف کرتا ہے؛abstract void write(int oneByte)
آؤٹ پٹ اسٹریم پر 1 بائٹ لکھتا ہے۔void write(byte[] buffer)
آؤٹ پٹ اسٹریم پر بائٹ سرنی لکھتا ہے۔void write(byte[] buffer, int offset, int count)
آفسیٹ پوزیشن سے شروع ہوتے ہوئے ایک صف سے گنتی بائٹس کی ایک رینج لکھتا ہے۔
OutputStream
:
-
DataOutputStream
. ایک آؤٹ پٹ سٹریم جس میں معیاری جاوا ڈیٹا کی قسمیں لکھنے کے طریقے شامل ہیں۔قدیم جاوا ڈیٹا کی اقسام اور تار لکھنے کے لیے ایک بہت ہی آسان کلاس۔ آپ شاید بغیر کسی وضاحت کے بھی درج ذیل کوڈ کو سمجھ جائیں گے۔
import java.io.*; public class DataOutputStreamExample { public static void main(String[] args) throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream("testFile.txt")); dos.writeUTF("SomeString"); dos.writeInt(22); dos.writeDouble(1.21323); dos.writeBoolean(true); } }
اس میں ہر قسم کے لیے الگ الگ طریقے ہیں —
writeDouble()
,writeLong()
,writeShort()
, اور اسی طرح۔ FileOutputStream
. یہ کلاس ڈسک پر موجود فائل میں ڈیٹا بھیجنے کا طریقہ کار نافذ کرتی ہے۔ ویسے، ہم نے اسے پہلے ہی آخری مثال میں استعمال کیا ہے۔ کیا آپ نے نوٹس کیا؟ ہم نے اسے DataOutputStream پر منتقل کیا، جس نے 'ریپر' کے طور پر کام کیا۔BufferedOutputStream
. ایک بفر شدہ آؤٹ پٹ سٹریم۔ یہاں کچھ بھی پیچیدہ نہیں ہے۔ اس کا مقصدBufferedInputStream
(یاBufferedReader
) کے مشابہ ہے۔ اعداد و شمار کی معمول کی ترتیب وار پڑھنے کے بجائے، یہ ایک خاص 'مجموعی' بفر کا استعمال کرتے ہوئے ڈیٹا لکھتا ہے۔ بفر ڈیٹا سنک تک رسائی کی تعداد کو کم کرنا ممکن بناتا ہے، اس طرح کارکردگی میں اضافہ ہوتا ہے۔import java.io.*; public class DataOutputStreamExample { public static void main(String[] args) throws IOException { FileOutputStream outputStream = new FileOutputStream("D:/Users/Username/someFile.txt"); BufferedOutputStream bufferedStream = new BufferedOutputStream(outputStream); String text = "I love Java!"; // We'll convert this string to a byte array and write it to a file byte[] buffer = text.getBytes(); bufferedStream.write(buffer, 0, buffer.length); } }
ایک بار پھر، آپ خود اس کوڈ کے ساتھ کھیل سکتے ہیں اور تصدیق کر سکتے ہیں کہ یہ آپ کے کمپیوٹر پر حقیقی فائلوں پر کام کرے گا۔
FileInputStream
ہمارے پاس , FileOutputStream
اور کے بارے میں ایک الگ سبق ہوگا BuffreredInputStream
، لہذا یہ پہلے جاننے والے کے لیے کافی معلومات ہے۔ یہی ہے! ہم امید کرتے ہیں کہ آپ انٹرفیس اور تجریدی کلاسوں کے درمیان فرق کو سمجھ گئے ہوں گے اور کسی بھی سوال کا جواب دینے کے لیے تیار ہوں گے، یہاں تک کہ چال والے سوالات بھی :)
GO TO FULL VERSION