
public class Car {
String model;
int maxSpeed;
public static void main(String[] args) {
Car car1 = new Car();
car1.model = "Ferrari";
car1.maxSpeed = 300;
Car car2 = new Car();
car2.model = "Ferrari";
car2.maxSpeed = 300;
System.out.println(car1 == car2);
}
}
کنسول آؤٹ پٹ:
false
ایسا لگتا ہے کہ ہم نے دو ایک جیسے کار آبجیکٹ بنائے ہیں: دونوں کار آبجیکٹ کے متعلقہ فیلڈز کی قدریں ایک جیسی ہیں، لیکن موازنہ کا نتیجہ اب بھی غلط ہے۔ ہم پہلے ہی وجہ جانتے ہیں: car1 اور car2 حوالہ جات مختلف میموری ایڈریسز کی طرف اشارہ کرتے ہیں، اس لیے وہ برابر نہیں ہیں۔ لیکن ہم اب بھی دو حوالوں کا نہیں بلکہ دو اشیاء کا موازنہ کرنا چاہتے ہیں۔ اشیاء کا موازنہ کرنے کا بہترین حل equals() طریقہ ہے۔
مساوی () طریقہ
آپ کو یاد ہوگا کہ ہم یہ طریقہ شروع سے نہیں بناتے ہیں، بلکہ ہم اسے اوور رائڈ کرتے ہیں: equals() طریقہ آبجیکٹ کلاس میں بیان کیا گیا ہے ۔ اس نے کہا، اس کی معمول کی شکل میں، یہ بہت کم فائدہ مند ہے:public boolean equals(Object obj) {
return (this == obj);
}
آبجیکٹ کلاس میں equals() طریقہ کی وضاحت اس طرح کی گئی ہے ۔ یہ ایک بار پھر حوالہ جات کا موازنہ ہے۔ انہوں نے ایسا کیوں کیا؟ ٹھیک ہے، زبان کے تخلیق کاروں کو کیسے معلوم ہوگا کہ آپ کے پروگرام میں کون سی اشیاء برابر سمجھی جاتی ہیں اور کون سی نہیں؟ :) یہ مساوی () طریقہ کار کا بنیادی نکتہ ہے — کلاس کا خالق وہ ہوتا ہے جو اس بات کا تعین کرتا ہے کہ کلاس کی اشیاء کی مساوات کو چیک کرتے وقت کون سی خصوصیات استعمال کی جاتی ہیں۔ پھر آپ اپنی کلاس میں equals() طریقہ کو اوور رائیڈ کرتے ہیں۔ اگر آپ "کون سی خصوصیات کا تعین کرتے ہیں" کے معنی کو بالکل نہیں سمجھتے ہیں، تو آئیے ایک مثال پر غور کریں۔ یہاں ایک سادہ کلاس ہے جو آدمی کی نمائندگی کرتی ہے: . Man
public class Man {
private String noseSize;
private String eyesColor;
private String haircut;
private boolean scars;
private int dnaCode;
public Man(String noseSize, String eyesColor, String haircut, boolean scars, int dnaCode) {
this.noseSize = noseSize;
this.eyesColor = eyesColor;
this.haircut = haircut;
this.scars = scars;
this.dnaCode = dnaCode;
}
// Getters, setters, etc.
}
فرض کریں کہ ہم ایک پروگرام لکھ رہے ہیں جس میں یہ تعین کرنے کی ضرورت ہے کہ آیا دو افراد ایک جیسے جڑواں ہیں یا صرف ایک جیسے ہیں۔ ہمارے پاس پانچ خصوصیات ہیں: ناک کا سائز، آنکھوں کا رنگ، بالوں کا انداز، نشانات کی موجودگی، اور ڈی این اے ٹیسٹ کے نتائج (سادگی کے لیے، ہم اس کو ایک عدد کوڈ کے طور پر پیش کرتے ہیں)۔ آپ کے خیال میں ان میں سے کون سی خصوصیات ہمارے پروگرام کو ایک جیسے جڑواں بچوں کی شناخت کرنے کی اجازت دے گی؟ 
equals()
طریقہ کار کے لیے اس کا کیا مطلب ہے؟ ہمیں Man
اپنے پروگرام کی ضروریات کو مدنظر رکھتے ہوئے اسے کلاس میں اوور رائڈ کرنے کی ضرورت ہے۔ طریقہ کار کو int dnaCode
دو اشیاء کے فیلڈ کا موازنہ کرنا چاہئے۔ اگر وہ برابر ہیں تو اشیاء برابر ہیں۔
@Override
public boolean equals(Object o) {
Man man = (Man) o;
return dnaCode == man.dnaCode;
}
کیا یہ واقعی اتنا آسان ہے؟ واقعی نہیں۔ ہم نے کچھ نظر انداز کیا۔ ہماری اشیاء کے لیے، ہم نے صرف ایک فیلڈ کی نشاندہی کی ہے جو آبجیکٹ کی مساوات قائم کرنے سے متعلق ہے: dnaCode
۔ اب تصور کریں کہ ہمارے پاس 1 نہیں بلکہ 50 متعلقہ فیلڈز ہیں۔ اور اگر دو آبجیکٹ کے تمام 50 فیلڈز برابر ہیں، تو اشیاء برابر ہیں۔ ایسا منظر نامہ بھی ممکن ہے۔ بنیادی مسئلہ یہ ہے کہ 50 شعبوں کا موازنہ کرکے مساوات قائم کرنا ایک وقت طلب اور وسائل کی ضرورت کا عمل ہے۔ اب تصور کریں کہ ہماری کلاس کے علاوہ Man
، ہمارے پاس Woman
بالکل وہی فیلڈز ہیں جو کہ میں موجود ہیں Man
۔ اگر کوئی دوسرا پروگرامر ہماری کلاسوں کا استعمال کرتا ہے، تو وہ آسانی سے اس طرح کوڈ لکھ سکتا ہے:
public static void main(String[] args) {
Man man = new Man(........); // A bunch of parameters in the constructor
Woman woman = new Woman(.........); // The same bunch of parameters.
System.out.println(man.equals(woman));
}
اس صورت میں، فیلڈ ویلیوز کی جانچ کرنا بے معنی ہے: ہم آسانی سے دیکھ سکتے ہیں کہ ہمارے پاس دو مختلف طبقات کی اشیاء ہیں، اس لیے ان کے برابر ہونے کا کوئی طریقہ نہیں ہے! equals()
اس کا مطلب ہے کہ ہمیں موازنہ اشیاء کی کلاسوں کا موازنہ کرتے ہوئے طریقہ میں ایک چیک شامل کرنا چاہئے ۔ یہ اچھا ہے کہ ہم نے اس کے بارے میں سوچا!
@Override
public boolean equals(Object o) {
if (getClass() != o.getClass()) return false;
Man man = (Man) o;
return dnaCode == man.dnaCode;
}
لیکن شاید ہم کچھ اور بھول گئے ہیں؟ ہمم... کم از کم، ہمیں یہ دیکھنا چاہیے کہ ہم کسی چیز کا اپنے آپ سے موازنہ تو نہیں کر رہے! اگر حوالہ A اور B ایک ہی میموری ایڈریس کی طرف اشارہ کرتے ہیں، تو وہ ایک ہی آبجیکٹ ہیں، اور ہمیں وقت ضائع کرنے اور 50 فیلڈز کا موازنہ کرنے کی ضرورت نہیں ہے۔
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (getClass() != o.getClass()) return false;
Man man = (Man) o;
return dnaCode == man.dnaCode;
}
اس کے لیے چیک شامل کرنے سے بھی کوئی تکلیف نہیں ہوتی null
: کوئی چیز برابر نہیں ہو سکتی null
۔ لہذا، اگر طریقہ پیرامیٹر کالعدم ہے، تو اضافی جانچ پڑتال کا کوئی فائدہ نہیں ہے۔ ان سب کو ذہن میں رکھتے ہوئے، پھر کلاس equals()
کے لیے ہمارا طریقہ Man
کچھ یوں نظر آتا ہے:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Man man = (Man) o;
return dnaCode == man.dnaCode;
}
ہم اوپر بیان کردہ تمام ابتدائی جانچ پڑتال کرتے ہیں۔ دن کے اختتام پر، اگر:
- ہم ایک ہی کلاس کی دو اشیاء کا موازنہ کر رہے ہیں۔
- اور موازنہ شدہ اشیاء ایک جیسی نہیں ہیں۔
- اور پاس شدہ اعتراض نہیں ہے۔
null
dnaCode
دو اشیاء کے فیلڈز۔ طریقہ کار کو اوور رائیڈ کرتے وقت equals()
، ان تقاضوں پر عمل کرنا یقینی بنائیں:
-
اضطراری صلاحیت۔
جب
equals()
طریقہ کسی بھی چیز کا اپنے آپ سے موازنہ کرنے کے لیے استعمال کیا جاتا ہے، تو اسے درست ہونا چاہیے۔
ہم نے پہلے ہی اس ضرورت کی تعمیل کی ہے۔ ہمارے طریقہ کار میں شامل ہیں:if (this == o) return true;
-
ہم آہنگی
اگر
a.equals(b) == true
، توb.equals(a)
واپس کرنا ضروری ہےtrue
.
ہمارا طریقہ اس ضرورت کو بھی پورا کرتا ہے۔ -
منتقلی
اگر دو اشیاء کسی تیسرے شے کے برابر ہیں، تو ان کا ایک دوسرے کے برابر ہونا چاہیے۔
اگرa.equals(b) == true
اورa.equals(c) == true
، پھرb.equals(c)
سچ بھی لوٹنا چاہیے۔ -
استقامت۔
کا نتیجہ
equals()
تب بدلنا چاہیے جب اس میں شامل فیلڈز کو تبدیل کیا جائے۔ اگر دونوں اشیاء کا ڈیٹا تبدیل نہیں ہوتا ہے، تو نتیجہequals()
ہمیشہ ایک جیسا ہونا چاہیے۔ -
کے ساتھ عدم مساوات
null
۔کسی بھی چیز کے لیے،
a.equals(null)
غلط کو واپس کرنا ضروری ہے
یہ صرف کچھ "مفید سفارشات" کا مجموعہ نہیں ہے، بلکہ ایک سخت معاہدہ ہے ، جو اوریکل دستاویزات میں بیان کیا گیا ہے۔
GO TO FULL VERSION