سلام اڄ اسان هڪ اهم ميکانيزم تي نظر ڪنداسين: وراثت ۾ نيسٽ ٿيل طبقن ۾. ڇا توهان ڪڏهن سوچيو آهي ته توهان ڇا ڪندا جيڪڏهن توهان کي ضرورت هجي ته هڪ نيسٽڊ ڪلاس کي ڪنهن ٻئي طبقي جو وارث بڻايو وڃي. جيڪڏهن نه، مون تي يقين ڪريو: اها صورتحال مونجهارو ٿي سگهي ٿي، ڇاڪاڻ ته اتي تمام گهڻيون شيون آهن.
- ڇا اسان نيسٽڊ ڪلاس کي ڪنهن طبقي جو وارث بڻائي رهيا آهيون؟ يا اسان ڪنهن طبقي کي نرالي طبقي جو وارث بڻائي رهيا آهيون؟
- ڇا ٻار/والدين طبقو هڪ عام عوامي طبقو آهي، يا اهو پڻ هڪ نرالو طبقو آهي؟
- آخرڪار، انهن سڀني حالتن ۾ اسان ڪهڙي قسم جي nested طبقن کي استعمال ڪندا آهيون؟
جامد نسٽڊ ڪلاس
سندن وراثت جا ضابطا سڀ کان سادو آهن. هتي توهان تقريبا هر شي ڪري سگهو ٿا جيڪو توهان جي دل چاهي ٿو. هڪ جامد نسٽڊ ڪلاس وارث ٿي سگھي ٿو:- هڪ عام طبقي
- هڪ جامد نسٽڊ ڪلاس جيڪو ٻاهرئين طبقي يا ان جي ابن ڏاڏن ۾ اعلان ڪيو ويو آهي
public class Boeing737 {
private int manufactureYear;
private static int maxPassengersCount = 300;
public Boeing737(int manufactureYear) {
this.manufactureYear = manufactureYear;
}
public int getManufactureYear() {
return manufactureYear;
}
public static class Drawing {
public static int getMaxPassengersCount() {
return maxPassengersCount;
}
}
}
اچو ته ڪوڊ کي تبديل ڪرڻ جي ڪوشش ڪريون ۽ هڪ Drawing
جامد نسٽڊ ڪلاس ۽ ان جو اولاد - Boeing737Drawing
.
public class Boeing737 {
private int manufactureYear;
private static int maxPassengersCount = 300;
public Boeing737(int manufactureYear) {
this.manufactureYear = manufactureYear;
}
public int getManufactureYear() {
return manufactureYear;
}
public static class Drawing {
}
public static class Boeing737Drawing extends Drawing {
public static int getMaxPassengersCount() {
return maxPassengersCount;
}
}
}
جئين توهان ڏسي سگهو ٿا، ڪو مسئلو ناهي. اسان طبقن کي به ڪڍي سگھون ٿا Drawing
۽ ان کي جامد نسٽڊ ڪلاس جي بدران هڪ عام عوامي طبقو بڻائي سگهون ٿا - ڪجھ به تبديل نه ٿيندو.
public class Drawing {
}
public class Boeing737 {
private int manufactureYear;
private static int maxPassengersCount = 300;
public Boeing737(int manufactureYear) {
this.manufactureYear = manufactureYear;
}
public int getManufactureYear() {
return manufactureYear;
}
public static class Boeing737Drawing extends Drawing {
public static int getMaxPassengersCount() {
return maxPassengersCount;
}
}
}
اسان اهو سمجهون ٿا. پر ڪهڙن طبقن کي وراثت ملي سگهي ٿو جامد نسٽڊ ڪلاس؟ عملي طور تي ڪو به! Nested/Non-nested, static/non-static - اهو فرق نٿو پوي. هتي اسان Boeing737Drawing
اندروني طبقي کي جامد نسٽڊ ڪلاس جو وارث بڻايون ٿا Drawing
:
public class Boeing737 {
private int manufactureYear;
private static int maxPassengersCount = 300;
public Boeing737(int manufactureYear) {
this.manufactureYear = manufactureYear;
}
public int getManufactureYear() {
return manufactureYear;
}
public static class Drawing {
}
public class Boeing737Drawing extends Drawing {
public int getMaxPassengersCount() {
return maxPassengersCount;
}
}
}
توھان ھن طرح ھڪڙو مثال ٺاھي سگھو ٿا Boeing737Drawing
:
public class Main {
public static void main(String[] args) {
Boeing737 boeing737 = new Boeing737(1990);
Boeing737.Boeing737Drawing drawing = boeing737.new Boeing737Drawing();
System.out.println(drawing.getMaxPassengersCount());
}
}
جيتوڻيڪ اسان جو Boeing737Drawing
طبقو هڪ جامد طبقو ورثي ۾ ملي ٿو، پر اهو خود جامد ناهي! نتيجي طور، ان کي هميشه ٻاهرين طبقي جي مثال جي ضرورت پوندي. اسان Boeing737Drawing
طبقن کي طبقن مان ڪڍي Boeing737
هڪ سادي عوامي طبقو بڻائي سگهون ٿا. ڪابه تبديلي ناهي. اهو اڃا تائين Drawing
جامد نسٽڊ ڪلاس کي وارث ڪري سگهي ٿو.
public class Boeing737 {
private int manufactureYear;
public static int maxPassengersCount = 300;
public Boeing737(int manufactureYear) {
this.manufactureYear = manufactureYear;
}
public int getManufactureYear() {
return manufactureYear;
}
public static class Drawing {
}
}
public class Boeing737Drawing extends Boeing737.Drawing {
public int getMaxPassengersCount() {
return Boeing737.maxPassengersCount;
}
صرف اهم نقطو اهو آهي ته هن معاملي ۾ اسان کي جامد maxPassengersCount
متغير عوامي بڻائڻ جي ضرورت آهي. جيڪڏهن اهو خانگي رهي ٿو ته پوءِ هڪ عام عوامي طبقي کي ان تائين رسائي نه هوندي. اسان جامد طبقن کي ڳولي ورتو آهي! :) هاڻي اچو ته اندروني طبقن ڏانهن وڃو. اهي 3 قسمن ۾ اچن ٿا: سادو اندروني طبقن، مقامي طبقن، ۽ گمنام اندروني طبقن. ٻيهر، اچو ته سادي کان پيچيده ڏانهن وڃو :)
گمنام اندروني طبقن
هڪ گمنام اندروني طبقو ٻئي طبقي جو وارث نٿو ٿي سگهي. ٻيو ڪو به طبقو گمنام طبقي جو وارث نٿو ٿي سگهي. اهو وڌيڪ آسان نه ٿي سگهي! :)مقامي طبقن
مقامي طبقن (جي صورت ۾ توهان وساري ڇڏيو) ٻئي طبقي جي ڪوڊ بلاڪ جي اندر اعلان ڪيو ويو آهي. گهڻو ڪري، اهو ٻاهرئين طبقي جي ڪجهه طريقن جي اندر ٿئي ٿو. منطقي طور تي، ساڳئي طريقي (يا ڪوڊ بلاڪ) اندر صرف ٻين مقامي طبقن کي مقامي طبقي جو وارث ڪري سگهي ٿو. هتي هڪ مثال آهي:public class PhoneNumberValidator {
public void validatePhoneNumber(final String number) {
class PhoneNumber {
private String phoneNumber;
public PhoneNumber() {
this.phoneNumber = number;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
class CellPhoneNumber extends PhoneNumber {
}
class LandlinePhoneNumber extends PhoneNumber {
}
// ...number validation code
}
}
هي ڪوڊ آهي اسان جي سبق مان مقامي ڪلاسن تي. اسان جي نمبر جي تصديق ڪندڙ طبقي ۾ PhoneNumber
مقامي ڪلاس آھي. جيڪڏهن اسان کي ضرورت هجي ته ٻن الڳ ادارن جي نمائندگي ڪرڻ لاءِ، مثال طور، هڪ موبائل فون نمبر ۽ هڪ لينڊ لائن فون نمبر، اسان اهو ڪري سگهون ٿا صرف هڪ ئي طريقي جي اندر. سبب سادو آهي: مقامي طبقي جو دائرو ان طريقي تائين محدود آهي (ڪوڊ بلاڪ) جتي اهو اعلان ڪيو ويو آهي. نتيجي طور، اسان ان کي خارجي طور استعمال ڪرڻ جي قابل نه هوندا (جنهن ۾ طبقاتي ورثي لاءِ). تنهن هوندي به، مقامي طبقي جي اندر وراثت جا امڪان تمام وسيع آهن! مقامي طبقو وارث ٿي سگھي ٿو:
- هڪ عام طبقو.
- هڪ اندروني طبقو جنهن کي ساڳئي طبقي ۾ مقامي طبقي يا ان جي ابن ڏاڏن مان هڪ ۾ قرار ڏنو ويو آهي.
- هڪ ٻيو مقامي ڪلاس ساڳئي طريقي سان اعلان ڪيو (ڪوڊ بلاڪ).
public class PhoneNumberValidator {
class PhoneNumber {
private String phoneNumber;
public PhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
public void validatePhoneNumber(final String number) {
class CellPhoneNumber extends PhoneNumber {
public CellPhoneNumber(String phoneNumber) {
super(number);
}
}
class LandlinePhoneNumber extends PhoneNumber {
public LandlinePhoneNumber(String phoneNumber) {
super(number);
}
}
// ...number validation code
}
}
هتي اسان PhoneNumber
ڪلاس کي طريقي مان ڪڍي validatePhoneNumber()
ان کي لوڪل ڪلاس بدران اندروني طبقو بڻايو. اهو اسان کي اسان جي 2 مقامي طبقن کي ان جو وارث بڻائڻ کان نٿو روڪي. مثال 2 - "... يا هن طبقي جي ابن ڏاڏن ۾." هاڻي اهو اڳ ۾ ئي وڌيڪ دلچسپ آهي. اسان PhoneNumber
وراثت جي زنجير ۾ اڃا به اڳتي وڌي سگهون ٿا. اچو ته هڪ تجريدي AbstractPhoneNumberValidator
طبقي جو اعلان ڪريون، جيڪو اسان جي طبقي جو ابن ڏاڏن بڻجي ويندو PhoneNumberValidator
:
public abstract class AbstractPhoneNumberValidator {
class PhoneNumber {
private String phoneNumber;
public PhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
}
جيئن توهان ڏسي سگهو ٿا، اسان صرف ان جو اعلان نه ڪيو - اسان PhoneNumber
ان ۾ اندروني طبقي کي پڻ منتقل ڪيو. بهرحال، ان جي اولاد ۾ PhoneNumberValidator
، طريقن ۾ اعلان ڪيل مقامي طبقن کي PhoneNumber
بغير ڪنهن مسئلي جي وارث ٿي سگهي ٿو!
public class PhoneNumberValidator extends AbstractPhoneNumberValidator {
public void validatePhoneNumber(final String number) {
class CellPhoneNumber extends PhoneNumber {
public CellPhoneNumber(String phoneNumber) {
super(number);
}
}
class LandlinePhoneNumber extends PhoneNumber {
public LandlinePhoneNumber(String phoneNumber) {
super(number);
}
}
// ...number validation code
}
}
وراثت واري لاڳاپي جي ڪري، هڪ نسلي طبقي جي اندر جي مقامي طبقن کي هڪ نسل جي اندر جي اندرين طبقن کي ”ڏس“ ٿو. ۽ آخرڪار، اچو ته آخري گروپ ڏانهن وڃو :)
اندروني طبقن
هڪ اندروني طبقي جو اعلان ڪيو ويو آهي ساڳئي ٻاهرئين طبقي ۾ (يا ان جي اولاد ۾) ٻئي اندروني طبقي کي وارث ڪري سگهي ٿو. اچو ته ان کي ڳوليون اسان جو مثال استعمال ڪندي سائيڪلن سان گڏ اندروني ڪلاسن جي سبق مان.public class Bicycle {
private String model;
private int maxWeight;
public Bicycle(String model, int maxWeight) {
this.model = model;
this.maxWeight = maxWeight;
}
public void start() {
System.out.println("Let's go!");
}
class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
class SportSeat extends Seat {
// ...methods
}
}
هتي اسان ڪلاس Seat
جي اندر جي اندروني طبقي جو اعلان ڪيو Bicycle
. ريسنگ سيٽ جو هڪ خاص قسم ، SportSeat
وراثت ۾ ملي ٿو. پر، اسان هڪ الڳ "ريسنگ سائيڪل" جو قسم ٺاهي سگھون ٿا ۽ ان کي الڳ ڪلاس ۾ رکون ٿا:
public class SportBicycle extends Bicycle {
public SportBicycle(String model, int maxWeight) {
super(model, maxWeight);
}
class SportSeat extends Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
}
هي پڻ هڪ اختيار آهي. اولاد جو اندروني طبقو ( SportBicycle.SportSeat
) ابن ڏاڏن جي اندروني طبقن کي "ڏس" ٿو ۽ انهن کي وارث ڪري سگهي ٿو. اندروني طبقن کي وراثت ۾ هڪ تمام اهم خصوصيت آهي! پوئين ٻن مثالن ۾، اسان جو SportSeat
ڪلاس هڪ اندروني طبقو هو. پر ڇا جيڪڏهن اسان فيصلو ڪريون ته SportSeat
هڪ عام عوامي طبقو جيڪو هڪ ئي وقت Seat
اندرين طبقي جو وارث هجي؟
// Error! No enclosing instance of type 'Bicycle' is in scope
class SportSeat extends Bicycle.Seat {
public SportSeat() {
}
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
اسان کي هڪ غلطي ملي آهي! ڇا توهان اندازو لڳائي سگهو ٿا ڇو؟ :) اهو سڀ ڪجهه سڌو آهي. جڏهن اسان اندروني طبقي جي ڳالهه ڪئي ته Bicycle.Seat
اسان اهو ذڪر ڪيو ته ٻاهرئين طبقي جي مثال جو حوالو واضح طور تي اندروني طبقي جي تعمير ڪندڙ ڏانهن منتقل ڪيو ويو آهي. هن جو مطلب آهي ته توهان هڪ Seat
اعتراض پيدا ڪرڻ کان سواء هڪ Bicycle
اعتراض پيدا نه ٿا ڪري سگهو. پر هڪ جي تخليق بابت ڇا SportSeat
؟ ان جي برعڪس Seat
، ان ۾ اهو ٺهيل ميڪانيزم نه آهي جنهن ۾ تعمير ڪندڙ کي ٻاهرئين طبقي جي هڪ مثال جي حوالي سان واضح طور تي منتقل ڪيو وڃي. S جيستائين، ڪنهن Bicycle
شئي کان سواءِ، اسان ڪا SportSeat
شئي ٺاهي نٿا سگهون، جيئن ته جي صورت ۾ Seat
. تنهن ڪري، اسان لاءِ صرف هڪ شيءِ باقي آهي - واضح طور تي SportSeat
تعمير ڪندڙ ڏانهن هڪ Bicycle
اعتراض جو حوالو. هتي اهو ڪيئن ڪجي:
class SportSeat extends Bicycle.Seat {
public SportSeat(Bicycle bicycle) {
bicycle.super();
}
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
اسان هاڻي استعمال ڪندي سپر ڪلاس تعمير ڪندڙ کي سڏيندا آهيون super();
، جيڪڏهن اسان هڪ اعتراض ٺاهڻ چاهيون ٿا SportSeat
، اسان کي ائين ڪرڻ کان ڪجھ به نه روڪيندو:
public class Main {
public static void main(String[] args) {
Bicycle bicycle = new Bicycle("Peugeot", 120);
SportSeat peugeotSportSeat = new SportSeat(bicycle);
}
}
اڙي! هي سبق ڪافي ڊگهو هو :) پر توهان تمام گهڻو سکيو! هاڻي اهو ڪجهه ڪمن کي حل ڪرڻ جو وقت آهي! :)
GO TO FULL VERSION