JavaRush /جاوا بلاگ /Random-UR /جاوا میں ایک سے زیادہ وراثت۔ ساخت بمقابلہ وراثت
DSergey_Kh
سطح

جاوا میں ایک سے زیادہ وراثت۔ ساخت بمقابلہ وراثت

گروپ میں شائع ہوا۔

جاوا میں ایک سے زیادہ وراثت

ایک سے زیادہ وراثت آپ کو ایک ایسی کلاس بنانے کی اجازت دیتی ہے جو متعدد سپر کلاسز سے وراثت میں ملتی ہے۔ کچھ دیگر مقبول آبجیکٹ پر مبنی پروگرامنگ زبانوں کے برعکس، جیسے C++، جاوا کلاسز سے متعدد وراثت کی اجازت نہیں دیتا ہے۔ جاوا متعدد طبقاتی وراثت کی حمایت نہیں کرتا ہے کیونکہ اس سے ہیرے کا مسئلہ پیدا ہو سکتا ہے۔ اور اس مسئلے کو حل کرنے کے طریقے تلاش کرنے کے بجائے، بہتر اختیارات ہیں کہ ہم ایک سے زیادہ وراثت کی طرح ایک ہی نتیجہ کیسے حاصل کر سکتے ہیں۔

ہیرے کا مسئلہ

ہیرے کے مسئلے کو زیادہ آسانی سے سمجھنے کے لیے، آئیے فرض کریں کہ جاوا میں ایک سے زیادہ وراثت کی حمایت کی گئی ہے۔ اس صورت میں، ہمارے پاس کلاس کا درجہ بندی ہو سکتی ہے جیسا کہ ذیل کی تصویر میں دکھایا گیا ہے۔ جاوا میں ایک سے زیادہ وراثت۔  ساخت بمقابلہ وراثت - 1آئیے مان لیتے ہیں کہ کلاس SuperClassخلاصہ ہے اور اس میں کچھ طریقہ کا اعلان کیا گیا ہے۔ دونوں کنکریٹ کلاسز ClassAاور ClassB.
package com.journaldev.inheritance;
public abstract class SuperClass {
	public abstract void doSomething();
}
package com.journaldev.inheritance;
public class ClassA extends SuperClass{
	@Override
	public void doSomething(){
		System.out.println("doSomething implementation of A");
	}
	//ClassA own method
	public void methodA(){
	}
}
package com.journaldev.inheritance;
public class ClassB extends SuperClass{
	@Override
	public void doSomething(){
		System.out.println("doSomething implementation of B");
	}
	//ClassB specific method
	public void methodB(){
	}
}
اب فرض کریں کہ ہم اسے نافذ کرنا چاہتے ہیں ClassCاور اسے ClassAاور سے وراثت میں لینا چاہتے ہیں ClassB۔
package com.journaldev.inheritance;
public class ClassC extends ClassA, ClassB{
	public void test(){
		//calling super class method
		doSomething();
	}
}
نوٹ کریں کہ طریقہ کار test()کو سپر کلاس طریقہ کہتے ہیں doSomething()۔ یہ ابہام کا باعث بنتا ہے کیونکہ مرتب کرنے والا نہیں جانتا کہ کون سا سپر کلاس طریقہ کار انجام دینا ہے۔ یہ ہیرے کی شکل کا کلاس ڈایاگرام ہے جسے ہیرے کا مسئلہ کہا جاتا ہے۔ یہ بنیادی وجہ ہے کہ جاوا متعدد وراثت کی حمایت نہیں کرتا ہے۔ نوٹ کریں کہ متعدد طبقاتی وراثت کے ساتھ مذکورہ مسئلہ صرف تین کلاسوں کے ساتھ ہوسکتا ہے جن میں کم از کم ایک مشترکہ طریقہ ہو۔

ایک سے زیادہ انٹرفیس وراثت

جاوا میں، ایک سے زیادہ وراثت کلاسوں میں تعاون یافتہ نہیں ہے، لیکن یہ انٹرفیس میں معاون ہے۔ اور ایک انٹرفیس بہت سے دوسرے انٹرفیس کو بڑھا سکتا ہے۔ ذیل میں ایک سادہ سی مثال ہے۔
package com.journaldev.inheritance;
public interface InterfaceA {
	public void doSomething();
}
package com.journaldev.inheritance;
public interface InterfaceB {
	public void doSomething();
}
نوٹ کریں کہ دونوں انٹرفیس ایک ہی طریقہ کا اعلان کرتے ہیں۔ اب ہم ایک انٹرفیس بنا سکتے ہیں جو ان دونوں انٹرفیس کو بڑھاتا ہے، جیسا کہ ذیل کی مثال میں دکھایا گیا ہے۔
package com.journaldev.inheritance;
public interface InterfaceC extends InterfaceA, InterfaceB {
	//same method is declared in InterfaceA and InterfaceB both
	public void doSomething();
}
یہ بہت اچھا کام کرتا ہے کیونکہ انٹرفیس صرف طریقوں کا اعلان کرتے ہیں اور عمل درآمد ان کلاسوں میں کیا جائے گا جو انٹرفیس کو وراثت میں حاصل کرتے ہیں۔ اس طرح، متعدد انٹرفیس وراثت میں ابہام حاصل کرنے کا کوئی طریقہ نہیں ہے۔
package com.journaldev.inheritance;
public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {
	@Override
	public void doSomething() {
		System.out.println("doSomething implementation of concrete class");
	}
	public static void main(String[] args) {
		InterfaceA objA = new InterfacesImpl();
		InterfaceB objB = new InterfacesImpl();
		InterfaceC objC = new InterfacesImpl();

		//all the method calls below are going to same concrete implementation
		objA.doSomething();
		objB.doSomething();
		objC.doSomething();
	}
}
براہ کرم نوٹ کریں کہ جب بھی آپ کسی بھی سپر کلاس طریقہ کو اوور رائیڈ کرتے ہیں یا انٹرفیس کا طریقہ نافذ کرتے ہیں تو تشریح کا استعمال کریں @Override۔ methodA()اگر ہم کلاس کا فنکشن اور کلاس میں کلاس کا ClassAفنکشن استعمال کرنا چاہتے ہیں تو کیا ہوگا ؟ حل مرکب کے استعمال میں مضمر ہے۔ ذیل میں کلاس کا ایک ورژن ہے جو کلاس کے طریقوں اور کسی ایک چیز کے طریقہ کار کی وضاحت کرنے کے لیے کمپوزیشن کا استعمال کرتا ہے۔ methodB()ClassBClassCClassCdoSomething()
package com.journaldev.inheritance;
public class ClassC{
	ClassA objA = new ClassA();
	ClassB objB = new ClassB();
	public void test(){
		objA.doSomething();
	}
	public void methodA(){
		objA.methodA();
	}
	public void methodB(){
		objB.methodB();
	}
}

ساخت بمقابلہ وراثت

جاوا پروگرامنگ کے بہترین طریقوں میں سے ایک "وراثت سے پہلے کمپوزیشن کی منظوری" ہے۔ ہم کچھ ایسے پہلوؤں کو تلاش کریں گے جو اس نقطہ نظر کے حق میں ہیں۔
  1. ہم کہتے ہیں کہ ہمارے پاس ایک سپر کلاس ہے اور ایک کلاس ہے جو اسے بڑھاتی ہے:

    package com.journaldev.inheritance;
    public class ClassC{
    	public void methodC(){
    	}
    }
    package com.journaldev.inheritance;
    public class ClassD extends ClassC{
    	public int test(){
    		return 0;
    	}
    }

    مذکورہ کوڈ مرتب کرتا ہے اور اچھی طرح کام کرتا ہے۔ لیکن، کیا ہوگا اگر ہم کلاس کے نفاذ کو تبدیل کریں ClassCجیسا کہ ذیل میں دکھایا گیا ہے:

    package com.journaldev.inheritance;
    public class ClassC{
    	public void methodC(){
    	}
    	public void test(){
    	}
    }

    نوٹ کریں کہ طریقہ test()ذیلی طبقے میں پہلے سے موجود ہے، لیکن واپسی کی قسم مختلف ہے۔ اب کلاس ClassDکمپائل نہیں ہوگی اور اگر آپ کوئی IDE استعمال کرتے ہیں تو یہ آپ کو سپر کلاس یا سب کلاس میں واپسی کی قسم کو تبدیل کرنے کا اشارہ کرے گا۔

    اب ایک ایسی صورتحال کا تصور کریں جہاں ہمارے پاس کثیر سطحی طبقاتی وراثت کا درجہ بندی ہے اور سپر کلاس تک رسائی نہیں ہے۔ تالیف کی غلطی کو دور کرنے کے لیے ہمارے پاس اپنے ذیلی طبقے کے طریقہ کار کے دستخط یا اس کا نام تبدیل کرنے کے سوا کوئی چارہ نہیں ہوگا۔ ہمیں ان تمام جگہوں پر سب کلاس طریقہ کو بھی تبدیل کرنا پڑے گا جہاں اسے کہا جاتا ہے۔ اس طرح، وراثت ہمارے کوڈ کو خراب کر دیتی ہے۔

    مندرجہ بالا مسئلہ مرکب کے ساتھ کبھی نہیں ہوگا اور یہ وراثت کے لئے زیادہ پرکشش بناتا ہے.

  2. وراثت کے ساتھ ایک اور مسئلہ یہ ہے کہ ہم سپر کلاس کے تمام طریقوں کو کلائنٹ کے سامنے ظاہر کرتے ہیں اور اگر ہماری سپر کلاس کو صحیح طریقے سے ڈیزائن نہیں کیا گیا ہے اور اس میں حفاظتی سوراخ ہیں، تو پھر بھی ہم اپنی کلاس کے بہترین نفاذ سے متاثر ہوتے ہیں۔ سپر کلاس کے کمپوزیشن سپر کلاس طریقوں تک کنٹرول رسائی فراہم کرنے میں ہماری مدد کرتی ہے، جبکہ وراثت سپر کلاس طریقوں پر کنٹرول فراہم نہیں کرتی ہے۔ یہ بھی وراثت سے مرکب کے اہم فوائد میں سے ایک ہے۔

  3. مرکب کا ایک اور فائدہ یہ ہے کہ یہ کال کرنے کے طریقوں میں لچک پیدا کرنے کی اجازت دیتا ہے۔ اوپر پیش کی گئی کلاس کا ہمارا نفاذ ClassCبہترین نہیں ہے اور اس بات کو یقینی بناتا ہے کہ مرتب کرنے کا وقت اس طریقہ سے منسلک ہے جسے کہا جائے گا۔ کم سے کم تبدیلیوں کے ساتھ ہم میتھڈ کال کو لچکدار اور متحرک بنا سکتے ہیں۔

    package com.journaldev.inheritance;
    public class ClassC{
    	SuperClass obj = null;
    	public ClassC(SuperClass o){
    		this.obj = o;
    	}
    	public void test(){
    		obj.doSomething();
    	}
    	public static void main(String args[]){
    		ClassC obj1 = new ClassC(new ClassA());
    		ClassC obj2 = new ClassC(new ClassB());
    
    		obj1.test();
    		obj2.test();
    	}
    }

    اوپر پیش کردہ پروگرام کا نتیجہ:

    doSomething implementation of A
    doSomething implementation of B

    میتھڈ کالنگ میں یہ لچک وراثت کے ساتھ دستیاب نہیں ہے، جس سے کمپوزیشن کے انتخاب میں ایک اور فائدہ ہوتا ہے۔

  4. یونٹ ٹیسٹنگ کمپوزیشن کے ساتھ کرنا آسان ہے کیونکہ ہم جانتے ہیں کہ ہم سپر کلاس کے تمام طریقے استعمال کر رہے ہیں اور انہیں ٹیسٹ کے لیے کاپی کر سکتے ہیں۔ جبکہ وراثت میں ہم سپر کلاس پر زیادہ انحصار کرتے ہیں اور سپر کلاس کے تمام طریقے نہیں جانتے جو استعمال کیے جائیں گے۔ لہذا ہمیں سپر کلاس کے تمام طریقوں کو جانچنا ہوگا، جو وراثت کی وجہ سے اضافی کام ہے۔

    مثالی طور پر، ہمیں وراثت کا استعمال صرف اس صورت میں کرنا چاہیے جب ذیلی طبقے سے سپرکلاس تعلق کو "is" کے طور پر بیان کیا جائے۔ دیگر تمام معاملات میں، یہ مرکب استعمال کرنے کی سفارش کی جاتی ہے.

تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION