տեղադրվել է Նարեշ Ջոշի կողմից 2018 թվականի նոյեմբերի 09-ին
Երբ մենք նույն անունով փոփոխական ենք ստեղծում և՛ ծնող, և՛ երեխա դասում, և փորձում ենք մուտք գործել դրան՝ օգտագործելով ծնողի դասի հղումը, որը պահում է երեխայի դասի օբյեկտը, ապա ի՞նչ ենք մենք ստանում:
Սա հասկանալու համար եկեք դիտարկենք ստորև բերված օրինակը, որտեղ մենք հայտարարում ենք x
փոփոխականը նույն անունով և՛ Parent
, և՛ Child
դասերում:
class Parent { // Declaring instance variable by name `x` String x = "Parent`s Instance Variable"; public void print() { System.out.println(x); } } class Child extends Parent { // Hiding Parent class's variable `x` by defining a variable in child class with same name. String x = "Child`s Instance Variable"; @Override public void print() { System.out.print(x); // If we still want to access variable from super class, we do that by using `super.x` System.out.print(", " + super.x + "\n"); } }
Եվ հիմա, եթե փորձենք մուտք գործել x
՝ օգտագործելով ստորև բերված կոդը, ինչ System.out.println(parent.x)
-ը կտպվի
Parent parent = new Child();
System.out.println(parent.x) // Output -- Parent`s Instance Variable
Դե, ընդհանուր առմամբ, մենք կասենք, որ Child
դասը կվերացնի Parent
դասում հայտարարված փոփոխականը, և parent.x
-ը մեզ կտա այն, ինչ Child's
օբյեկտը պահում է: Որովհետև դա նույնն է, ինչ տեղի է ունենում, երբ մենք նույն տեսակի գործողություն ենք կատարում մեթոդների վրա:
Բայց իրականում դա այդպես չէ, և parent.x
-ը մեզ արժեք կտա Parent`s Instance Variable-ը, որը հայտարարված է Parent
դասում, բայց ինչու:
Քանի որ Java-ում փոփոխականները չեն հետևում պոլիմորֆիզմին, և գերակայությունը կիրառելի է միայն մեթոդների, բայց ոչ փոփոխականների համար: Եվ երբ երեխայի դասի օրինակի փոփոխականն ունի նույն անունը, ինչ մայր դասի օրինակի փոփոխականը, ապա օրինակի փոփոխականն ընտրվում է հղման տեսակից:
Java-ում, երբ մենք Child դասի փոփոխական ենք սահմանում անունով, որը մենք արդեն օգտագործել ենք Parent դասում փոփոխական սահմանելու համար, Child դասի փոփոխականը թաքցնում է ծնողի փոփոխականը, նույնիսկ եթե դրանց տեսակները տարբեր են: Եվ այս հայեցակարգը հայտնի է որպես Փոփոխական թաքցնում
Այլ կերպ ասած, երբ երեխա և ծնող դասը երկուսն էլ ունեն նույն անունով փոփոխական, Child դասի փոփոխականը թաքցնում է ծնող դասի փոփոխականը: Փոփոխականների թաքցման մասին ավելին կարող եք կարդալ Ի՞նչ է փոփոխական ստվերումը և թաքցնելը Java-ում հոդվածում:
Փոփոխական թաքցնելը նույնը չէ, ինչ մեթոդի գերակայումը
Թեև փոփոխականի թաքցումը կարծես փոփոխականի վերացում է, որը նման է մեթոդի գերակայմանը, բայց դա այդպես չէ, գերակայումը կիրառելի է միայն մեթոդների համար, մինչդեռ թաքցումը կիրառելի է փոփոխականների համար:
մեթոդների գերակայման դեպքում, գերակայող մեթոդներն ամբողջությամբ փոխարինում են ժառանգված մեթոդներին, այնպես որ, երբ մենք փորձում ենք մեթոդին մուտք գործել ծնողի հղումից՝ երեխայի օբյեկտը պահելով, երեխայի դասի մեթոդը կանչվում է: Դուք կարող եք ավելին կարդալ գերագնահատման մասին, և թե ինչպես են անտեսված մեթոդները ամբողջությամբ փոխարինում ժառանգված մեթոդներին Ամեն ինչ մեթոդի գերբեռնման և մեթոդի գերակայման մասին, Ինչու պետք է հետևենք մեթոդի վերացման կանոններին:
Բայց փոփոխական թաքցնում երեխայի դասը թաքցնում է ժառանգված փոփոխականները փոխարինելու փոխարեն, ինչը հիմնականում նշանակում է, որ Child դասի օբյեկտը պարունակում է երկու փոփոխականներ, իսկ Child’s փոփոխականը թաքցնում է Ծնողի փոփոխականը: Այսպիսով, երբ մենք փորձում ենք փոփոխականին մուտք գործել Child դասից, այն հասանելի կլինի երեխայի դասից:
Իսկ եթե պարզեցնեմ Օրինակ 8.3.1.1–3. «Java լեզվի ճշգրտման օրինակի փոփոխականների թաքցում.
Երբ մենք հայտարարում ենք փոփոխական
Child
դասում, որն ունի նույն անունը, օրինակ.x
որպես օրինակի փոփոխականParent
դասում, ապա
1. Child class-ի օբյեկտը պարունակում է երկու փոփոխականներ (մեկը ժառանգված է
Parent
դասից, իսկ մյուսը հայտարարված էChild
-ում), սակայն երեխայի դասի փոփոխականը թաքցնում է ծնող դասի փոփոխականը:
2. Քանի որ
x
-ի հայտարարագիրըChild
դասում թաքցնում էx
-ի սահմանումըParent
դասում,Child
դասի հայտարարագրում,x
պարզ անունը միշտ վերաբերում էChild
դասում հայտարարված դաշտին: Եվ եթեChild
դասի մեթոդների կոդը ցանկանում է վերաբերելParent
դասիx
փոփոխականին, ապա դա կարելի է անել որպեսsuper.x
:
3. Եթե մենք փորձում ենք մուտք գործել փոփոխական
Parent
ևChild
դասերից դուրս, ապա օրինակի փոփոխականն ընտրվում է հղման տեսակից: Այսպիսով,parent2.x
արտահայտությունը հետևյալ կոդի մեջ տալիս է փոփոխական արժեքը, որը պատկանում է մայր դասին, նույնիսկ եթե այն պահում էChild
-ի օբյեկտը, բայց((Child) parent2).x
-ը մուտք է գործումChild
դասի արժեքը, քանի որ մենք նույն հղումն ենք տալիսChild
ին:
Ինչու է փոփոխական թաքցումը նախագծված այս կերպ
Ուրեմն մենք գիտենք, որ օրինակի փոփոխականներն ընտրվում են հղման տիպից, այլ ոչ թե օրինակի տեսակից, և պոլիմորֆիզմը կիրառելի չէ փոփոխականների համարբայց իրական հարցն այն է, թե ինչու: ինչու են փոփոխականները նախագծված հետևելու թաքցնելու փոխարեն գերակայելու: Քանի որ փոփոխականի գերակայումը կարող է կոտրել ծնողից ժառանգված մեթոդները, եթե մենք փոխենք դրա տեսակը երեխայի դասում:
Մենք գիտենք, որ յուրաքանչյուր երեխա դաս ժառանգում է փոփոխականներ և մեթոդներ (վիճակ և վարքագիծ) իր ծնող դասից: Պատկերացրեք, եթե Java-ն թույլ տա փոփոխականների գերակայում, և մենք փոփոխականի տեսակը փոխենք int
-ից Object
-ի երեխայի դասում: Այն կխախտի ցանկացած մեթոդ, որն օգտագործում է այդ փոփոխականը, և քանի որ երեխան ժառանգել է այդ մեթոդները ծնողից, կոմպիլյատորը սխալներ կտա child
դասում:
Օրինակ:
class Parent { int x; public int increment() { return ++x; } public int getX() { return x; } } class Child extends Parent { Object x; // Child is inherting increment(), getX() from Parent and both methods returns an int // But in child class type of x is Object, so increment(), getX() will fail to compile. }
Եթե Child.x
-ը գերազանցում է Parent.x
-ը, ինչպե՞ս կարող են աշխատել increment()
-ը և getX()
-ը: Ենթադասում այս մեթոդները կփորձեն վերադարձնել սխալ տեսակի դաշտի արժեքը: Եվ ինչպես նշվեց, եթե Java-ն թույլատրում է փոփոխականի գերակայությունը, ապա Child's փոփոխականը չի կարող փոխարինել ծնողի փոփոխականին, և դա կխախտի Liskov փոխարինելիության սկզբունքը (LSP):
Նմանապես, կոմպիլյացիայի ժամանակ փոփոխական մուտքը նույնպես վերաբերվում է հղման տիպին, սակայն, ինչպես մենք քննարկեցինք, փոփոխականները չեն հետևում գերակայող կամ գործարկման ժամանակի պոլիմորֆիզմին, ուստի դրանք չեն փոխարինվում գործարկման ժամանակ երեխայի դասի փոփոխականներով և դեռ վերաբերում են հղման տիպին:
Ընդհանուր առմամբ, ոչ ոք երբեք խորհուրդ չի տա թաքցնել դաշտերը, քանի որ դա դժվարացնում է կոդը կարդալը և շփոթություն է առաջացնում: Այսպիսի շփոթություն չի առաջանա, եթե մենք միշտ հավատարիմ մնանք POJO-ներ ստեղծելու ընդհանուր ուղեցույցներին և ամփոփենք մեր դաշտերը՝ դրանք հայտարարելով որպես մասնավոր և տրամադրենք ստացողներ/սահմանիչներ, ինչպես պահանջվում է, որպեսզի փոփոխականները տեսանելի չլինեն այդ դասից դուրս, և երեխաների դասը չկարողանա մուտք գործել դրանց: .
Դուք կարող եք գտնել ամբողջական կոդը այս Github Repository-ում և խնդրում ենք ազատ զգալ տրամադրել ձեր արժեքավոր կարծիքը:
Սկզբնապես հրապարակվել է www.programmingmitra.com կայքում: