"Bağlama" nədir və onu gecikdirən nədir? - Kodda inanılmaz sərgüzəştlər. Erkən və gec bağlanma. Dinamik polimorfizm
--- .NET yığıncaqları --- Gec bağlanma
Gec bağlama (gec bağlama) müəyyən bir növün nümunəsini yaratmağa və tərtib zamanı onun mövcudluğu faktını kodlaşdırmadan onun üzvlərini iş vaxtında çağırmağa imkan verən texnologiyadır. Bəzi xarici montajdan bir növə gec bağlanmanı təmin edən proqram yaratdığınız zaman həmin montaja istinad əlavə etmək üçün heç bir səbəb yoxdur və buna görə də çağırış kodunun manifestində birbaşa göstərilmir.
İlk baxışdan gec bağlamanın faydasını görmək asan deyil. Həqiqətən də, əgər obyektə erkən bağlama etmək mümkündürsə (məsələn, montaj arayışı əlavə edin və növü yeni açar sözlə yerləşdirin), siz mütləq bunu etməlisiniz. Ən cəlbedici səbəblərdən biri odur ki, erkən bağlama xətaların icra vaxtında deyil, tərtib zamanı tutulmasına imkan verir. Bununla belə, gec bağlama da yaratdığınız hər hansı genişləndirilə bilən proqramda mühüm rol oynayır.
System.Activator sinfi
Sistem sinfi. Aktivator (mscorlib.dll yığıncağında müəyyən edilir) .NET-də gec bağlanma prosesində əsas rol oynayır. İndiki nümunədə, hələlik, yalnız maraq doğurur Activator.CreateInstance() metodu, bu sizə gec bağlanacaq növün nümunəsini yaratmağa imkan verəcək. Bu üsul bir neçə həddindən artıq yükə malikdir və buna görə də kifayət qədər yüksək dərəcədə rahatlıq təmin edir. Ən sadə versiyasında CreateInstance() yaddaşda tez bir zamanda ayrılacaq obyekti təsvir edən etibarlı Type obyektini götürür.
Nə demək istədiyimizi görmək üçün Konsol Tətbiqi tipli yeni layihə yaradaq, using açar sözündən istifadə etməklə System.I0 və System.Reflection ad boşluqlarını ona idxal edək və sonra aşağıda göstərildiyi kimi Proqram sinfini dəyişdirək:
Sistemdən istifadə; System.Reflection istifadə edərək; System.IO istifadə edərək; ad sahəsi ConsoleApplication1 ( sinif Proqramı ( statik boşluq Main() ( Assambleya ass = null; cəhd edin ( ass = Assembly.Load("fontinfo"); ) catch (FileNotFoundException ex) ( Console.WriteLine(ex.Message); ) əgər (ass) != null) CreateBinding(ass); Console.ReadLine(); ) statik etibarsız CreateBinding(Assembly a) ( cəhd edin ( Type color1 = a.GetType("FontColor"); // Gecikmiş bağlama obyektindən istifadə edin obj = Activator.CreateInstance( color1); Console.WriteLine("Obyekt yaradıldı!"); ) tutmaq (İstisna məsələn) ( Console.WriteLine(ex.Message); ) ) ) )
Bu proqramı işə salmazdan əvvəl, Windows Explorer istifadə edərək, fontinfo.dll məclisini bu yeni proqramın kataloqu altındakı bin\Debug alt kataloquna əl ilə kopyalamalısınız. Fakt budur ki, Assembly.Load() metodu burada çağırılır, bu o deməkdir ki, CLR mühiti yalnız müştəri qovluğunu yoxlayacaq (arzu edilərsə, Assembly.LoadFrom() metodundan istifadə edib montaja tam yolu göstərə bilərsiniz, lakin bu lazım deyil).
Virtual funksiyaların istifadəsinə toxunmazdan əvvəl erkən və gec bağlanma kimi anlayışları nəzərə almaq lazımdır. Gəlin, məsələn, bir kiloqram portağal almaq üçün iki yanaşmanı müqayisə edək. Birinci halda, əvvəlcədən bilirik ki, 1 kq almaq lazımdır. portağal. Ona görə də kiçik paket götürürük, çox deyil, bu kiloqrama çatacaq qədər pul. İkinci halda, biz evdən çıxarkən nəyi və nə qədər almalıyıq, bilmirik. Buna görə də bir avtomobil götürürük (əgər çox şeylər və ağır şeylər olacaqsa), böyük və kiçik ölçülü bağlamalara yığırıq və mümkün qədər çox pul götürürük. Bazara gedirik və belə çıxır ki, cəmi 1 kq almaq lazımdır. portağal.
Yuxarıdakı nümunə müəyyən dərəcədə erkən və gec bağlamanın istifadəsinin mənasını əks etdirir. Aydındır ki, bu nümunə üçün birinci seçim optimaldır. İkinci halda, biz çox şey qabaqcadan görmüşük, lakin buna ehtiyacımız yox idi. Digər tərəfdən, əgər bazara gedərkən portağal lazım olmadığına qərar verərsək və 10 kq almağa qərar veririk. alma, onda birinci halda biz artıq bunu edə bilməyəcəyik. İkinci halda, bu asandır.
İndi bu nümunəni proqramlaşdırma baxımından nəzərdən keçirin. Erkən bağlamadan istifadə edərkən biz bir növ tərtibçiyə deyirik: "Mən nə istədiyimi dəqiq bilirəm. Buna görə də, bütün funksiya çağırışlarını sərt (statik) bağlayın." Gecikmiş bağlama mexanizmindən istifadə edərkən biz tərtibçiyə bir növ deyirik: "Mən hələ nə istədiyimi bilmirəm. Vaxtı gələndə sizə nə və necə istədiyimi deyəcəyəm."
Beləliklə, erkən bağlama zamanı zəng edən və zəng edən şəxs ilk fürsətdə, adətən tərtib zamanı bağlanır.
Çağırılan metod və çağırış metodu gec bağlandıqda, onlar kompilyasiya zamanı bağlana bilməz. Buna görə də, zəng həqiqətən edilən zaman çağırılan və çağırış metodlarının necə bağlanacağını müəyyən edən xüsusi bir mexanizm tətbiq edilmişdir.
Aydındır ki, erkən bağlamanın sürəti və səmərəliliyi gec bağlamadan daha yüksəkdir. Eyni zamanda, gec bağlama bəzi bağlama elastikliyini təmin edir.
Nəhayət, virtual funksiyalara və metodlara gəldik. Təəssüf ki, virtual metodları təsvir etmək üçün fiziki dünya ilə hər hansı bir analogiya çəkmək olduqca çətindir. Ona görə də proqramlaşdırma baxımından dərhal bu məsələyə baxacağıq.
Bəs virtual üsullar nə üçün istifadə olunur? Virtual üsullar mövcuddur ki, "varis" onunla uyğunluq xassəsini saxlayaraq, "əcdad"dan fərqli davransın.
Budur virtual metodların tərifi:
virtual üsul nəsildə elan olunduqda, hər yerdə, hətta bir nəsildə elan edilən üsullarda belə, uyğun metodu əvəz edən bir üsuldur..
Virtual metodun ünvanı yalnız proqramın icrası zamanı məlum olur. Virtual metod çağırıldıqda onun ünvanı öz sinfinin virtual metod cədvəlindən götürülür. Beləliklə, lazım olan şey deyilir.
Virtual metodlardan istifadənin üstünlüyü ondan ibarətdir ki, o, kompilyasiya zamanı növü məlum olmayan obyektlərin işlənməsinə imkan verən gec bağlama mexanizmindən tam istifadə edir.
Virtual üsullardan istifadəni göstərmək üçün dildə bir misal verəcəm C++ birindən borc almışam C++ Dərsliyi. Bu dillə o qədər də tanış olmasanız belə, ümid edirəm ki, mənim izahatlarım heç olmasa bir şəkildə onun mənasını izah edəcək.
#daxildir
Proqramın nəticələri (ekrandakı çıxış):
Avtomobil Avtomobil Vasitə Qayıq
Verilmiş nümunəni nəzərdən keçirək. Üç sinifimiz var avtomobil, yük maşını və qayıq, əsas sinifdən əldə edilən nəqliyyat vasitəsi. Əsas sinifdə nəqliyyat vasitəsi virtual funksiya təsvir edilmişdir mesaj. Üç sinifdən ikisində avtomobil, qayıq) funksiyalarını da təsvir edir mesaj, və sinifdə yük maşını funksiyasının təsviri yoxdur mesaj. Şərh etmədiyim bütün sətirlərin bu misal üçün heç bir əsas mənası yoxdur. İndi proqramın əsas blokuna - funksiyalara keçək əsas(). Bir dəyişəni təsvir etmək tək velosiped, tipli obyektin göstəricisi kimi nəqliyyat vasitəsi. Mən bir obyektin niyə məhz göstərici olduğunu təfərrüatlara daxil etməyəcəyəm. Deməli, lazımdır. Bu halda göstəriciyə obyektin özü kimi yanaşın. Göstəricilərlə işin təfərrüatlarını müəyyən bir OOP dilinin təsvirlərində tapmaq olar. Sonra sinfin obyektini yaradırıq nəqliyyat vasitəsi, dəyişən tək velosiped bu obyektə işarə edir. Bundan sonra metodu çağırırıq mesaj obyekt tək velosiped, və növbəti sətirdə bu obyekti silirik. 3 sətirdən ibarət növbəti üç blokda oxşar əməliyyatları həyata keçiririk, yeganə fərq sinif obyektləri ilə işləməyimizdir. avtomobil, yük maşını, qayıq. Göstəricidən istifadə bizə bütün törəmə siniflər üçün eyni göstəricidən istifadə etməyə imkan verir. Biz funksiyanı çağırmaqda maraqlıyıq mesaj obyektlərin hər biri üçün. Funksiyasını göstərməmişiksə mesaj sinif nəqliyyat vasitəsi virtualdır ( virtual), onda kompilyator istənilən metod çağırışını göstərici obyektinə statik (sərt) bağlayacaq tək velosipedüsulu ilə mesaj sinif nəqliyyat vasitəsi, çünki izah edərkən dəyişən dedik tək velosiped sinif obyektinə işarə edir nəqliyyat vasitəsi. Bunlar. erkən bağlanma yaradacaq. Belə bir proqramın çıxışı dörd sətrin çıxışı olacaq "Nəqliyyat vasitəsi". Amma sinifdə virtual funksiyadan istifadə etdiyimiz üçün bir qədər fərqli nəticələr əldə etdik.
Sinif obyektləri ilə işləyərkən avtomobil və qayıqöz üsulları adlanır mesaj, bu, müvafiq mesajların ekranda göstərilməsi ilə təsdiqlənir. Sinifdə yük maşınıüsul yoxdur mesaj, bu səbəbdən əsas sinfin müvafiq metodu çağırılır nəqliyyat vasitəsi.
Çox vaxt virtual metodu ehtiva edən sinifə polimorfik sinif deyilir. Ən mühüm fərq ondan ibarətdir ki, polimorf siniflər tərtib zamanı növü məlum olmayan obyektlərin işlənməsinə imkan verir. Baza sinfində virtual olaraq elan edilən funksiyalar törəmə siniflərdə dəyişdirilə bilər və bağlama tərtib mərhələsində deyil (erkən bağlama adlanır), lakin metodun çağırıldığı anda (gec bağlama) baş verəcəkdir.
Virtual üsullar açar sözdən istifadə etməklə təsvir olunur virtualəsas sinifdə. Bu o deməkdir ki, törəmə sinifdə bu metod həmin törəmə sinif üçün daha uyğun olan üsulla əvəz edilə bilər. Əsas sinifdə virtual elan edilən metod bütün törəmə siniflər üçün virtual qalacaq. Əgər virtual metod törəmə sinifdə ləğv edilməyibsə, o zaman çağırış sinif iyerarxiyasında (yəni, əsas sinifdə) bu adla bir metod tapacaq.
Virtual funksiyalar haqqında danışılacaq son şey abstrakt siniflər anlayışıdır. Ancaq növbəti addımda buna baxacağıq.
I. OOP-un əsas prinsipləri
1. İnkapsulyasiya- verilənlərin və onların emalı üçün alqoritmlərin vahid bütövlükdə birləşdirilməsindən ibarət OOP prinsipi.
OOP-da obyekt verilənləri adlanır obyekt sahələri , və alqoritmlər, yəni obyekt verilənləri üzərində hərəkətlər deyilir obyekt metodları , alt proqramlar şəklində düzülmüşdür.
2. Vərəsəlik- obyektlərin öz nəsillərini yaratmaq üçün mülkiyyətindən ibarət olan OOP prinsipi.
Uşaq obyekti avtomatik olaraq bütün sahə və metodları valideyndən miras alır, obyektləri yeni sahələrlə tamamlaya və valideynin metodlarını əvəz edə və ya əlavə edə bilər.
3. Polimorfizm- bu, mənaca oxşar problemləri müxtəlif yollarla həll etmək üçün bir ümumi valideyni olan obyektlərin mülkiyyətidir.
Metod Polimorfizmiəcdadda və nəsildə eyniadlı üsulların müxtəlif həyata keçirilməsində olması ilə ifadə edilir.
II. Obyekt tipi bəyannaməsinin strukturu
<имя_типа>=OBYEKT
<имя_поля>:<тип_поля>;
<методы>;
Obyektin tipini təyin etdikdən sonra, obyekt tipində sadalanan bütün metodların təsvirləri izlənməlidir ki, bunlar prosedur və funksiyaların mətnləridir. Adi təsvirdən fərqi ondadır alt proqram adı başlığında göstərilən obyekt metodu olan 2 hissədən ibarətdir:
<имя_типа>.<имя_подпрограммы>
III. Miras Mülkiyyəti
ana növü Bütün sahələrin və metodların miras alındığı. Bunun baş verməsi üçün miras, sonra obyekt tipinin tərifinə OBYEKT mötərizələr əsas növün adı olmalıdır.
vərəsəlik qaydaları.
1. Vərəsə növünün müəyyən edilməsində valideynin sahələri ilə eyni adda olan sahələr olmamalıdır; varislərin və valideynin üsullarının adları eyni ola bilər - bu özünü göstərir polimorfizm xüsusiyyəti .
2. Vərəsə obyekt tipini qurarkən ilk növbədə valideynin sahələri miras alınır, sonra varisin sahələri əlavə olunur; sahələrdən sonra valideynin bütün üsulları miras alınır, sonra onların adları valideynin metodlarının adları ilə uyğun gəlmirsə, vərəsələrin üsulları əlavə edilir; uyğunluqlar varsa, bu, varis metodlarının olması deməkdir polimorfik üsullar və eyni adlı əcdad üsullarını əvəz edin.
polimorfizm xüsusiyyəti.
Polimorfizm xüsusiyyəti ondan ibarətdir ki, vərəsələrin növünün müəyyən edilməsində valideynin üsullarının adları ilə eyni adlı üsullar ola bilər.
Polimorfizm üçün miras qaydaları:
· varisin eyniadlı üsulları valideynin metodlarını əvəz edir;
· valideynin metodlarından sonra valideynin metodlarının adlarına uyğun gəlməyən vərəsə üsulları əlavə edilir.
IV. Virtual üsullar
Obyektin metodları bunlardır statik üsullar əgər kompilyator onları ayırırsa və kompilyasiya və keçid vaxtında onlara bütün istinadları həll edirsə. Statik metodlara edilən çağırışların kompilyasiya zamanı kompilyator tərəfindən birmənalı şəkildə həll edilməsi prosesi adlanır. erkən bağlama .
Gec bağlama, çağırma və çağırma üsullarında kompilyasiya zamanı ünvanlarla bağlana bilməz, ona görə də zəng faktiki baş verdiyi anda, yəni proqramın icrası zamanı bağlamanın yerinə yetirilməsinə imkan verən mexanizm işə salınır.
Virtual Metodlar və Virtual Metod Cədvəli (TVM).
Gecikmiş bağlama istifadə edərək həyata keçirilir virtual üsullar , hansı xüsusiyyət açar sözün olmasıdır VİRTUAL obyekt tipi tərifində metod başlığından sonra.
Gec bağlama ilə edilir virtual metod cədvəlləri (TVM), proqramda təsvir edilən bütün virtual metodlar üçün proqram verilənləri seqmentində tərtibçi tərəfindən qurulan. TVM virtual üsullar olan prosedurların ünvanları cədvəlidir. Tərkibində virtual metodlar olan istənilən obyekt virtual metod cədvəlinin nümunəsinin yaddaşda olmasını tələb edir.Hər obyekt növü üçün yalnız bir TBM qurulur. Virtual metod cədvəlinin göstəricisi konstruktor yerinə yetirildikdə obyekt tipinin hər bir nümunəsində mövcud olan xüsusi sahədə avtomatik olaraq doldurulur. Bu göstərici vasitəsilə TVM-ə giriş virtual metoda hər zənglə baş verir.
Konstruktor.
konstruktor üsulu
Konstruktor gec bağlamaya imkan vermək üçün quraşdırma işlərini yerinə yetirən xüsusi bir prosedur növüdür. Virtual metodları olan bütün obyekt tiplərində həmişə virtual metoda ilk çağırışdan əvvəl çağırılan konstruktor olmalıdır. Konstruktora əvvəlki çağırış olmadan virtual metodun çağırılması sistemi bloklaya bilər.
Yalnız bir prosedur konstruktor ola bilər, onun başlığında xidmət sözü əvəzinə PROSEDUR yazmaq lazımdır İNŞAATÇI.
Konstruktor virtual ola bilməz.
Konstruktor metodu icra edildikdən sonra virtual metodlar çağırıldıqda onların ünvanları TVM-dən müəyyən edilir.
Dağıdıcı.
Dağıdıcı yaddaşı təmizləmək və dinamik olaraq ayrılmış obyekti silmək üçün istifadə olunur. Adətən, dağıdıcı obyektlə son hərəkətləri təyin edir. Dağıdıcının başlığında xidmət sözü PROSEDUR ilə əvəz olunur DESTRUKTOR Eyni obyekt növü üçün bir neçə dağıdıcı təyin edə bilərsiniz. Destruktorlar miras qala bilər, onlar statik və ya virtual ola bilər.
V. Obyekt tipinin nümunəsi
1. Problemin ifadəsi: ekranda bir nöqtənin hərəkətini həyata keçirin.
2. Riyazi model: ekranda hər bir nöqtə koordinatlarla xarakterizə olunur x, y və dövlət v-görünən/görünməz.
3. Obyekt tipli nöqtənin bəyanı:
POINT=obyekt
X, Y: tam ədəd; (koordinatlar)
V: boolean (görünürlük bayrağı: TRUE-görünür; FALSE-görünməz)
GET_X funksiyası: tam ədəd; (x koordinatını əldə edin)
GET_Y funksiyası: tam ədəd; (Y koordinatını alın)
GET_V funksiyası: boolean; (görünmə işarəsi almaq)
prosedur INIT(X0, Y0: tam ədəd); (koordinatları təyin edin)
TURN_ON proseduru; (nöqtə çəkmək - görünən bir nöqtə əldə etmək)
prosedur TURN_OFF; (nöqtə silmək - görünməz bir nöqtə əldə etmək)
MOVE proseduru(XN, YN: tam ədəd); (hərəkət nöqtəsi)
4. POINT obyektinin metodlarının müəyyən edilməsi:
POINT.GET_X funksiyası; (x koordinatını əldə edin)
GET_X:=X;
POINT.GET_Y funksiyası; (Y koordinatını alın)
GET_Y:=Y;
POINT.GET_V funksiyası; (görünmə işarəsi almaq)
GET_V:=V;
prosedur POINT.INIT; (koordinatları təyin edin)
V:=false;
prosedur POINT.TURN_ON; (görünən nöqtəni əldə edin)
olmasa V
PutPixel(X,Y,GetColor); ( GetColor cari rəngi qaytarır )
V:=doğru;
prosedur POINT.TURN_OFF; (görünməz bir nöqtə əldə etmək - bir nöqtəni silmək)
əgər V
PutPixel(X,Y,GetBkColor); ( GetBkColor fon rəngini qaytarır )
V:=false;
POINT.MOVE proseduru; (hərəkət nöqtəsi)
F: boolean
əgər F
SÖNDÜR;
əgər F
İŞƏ SAL;
Vərəsəlik mülkiyyəti.
Nöqtəyə əlavə olaraq, həndəsi fiqurları təsvir edən digər obyektləri, məsələn, tipli bir obyekti təyin edə bilərsiniz. dairə, müəyyən edilir radius, mərkəz koordinatı, görünürlük işarəsi, və onunla eyni hərəkətlər bir nöqtə ilə mümkündür: görünən bir dairə əldə etmək; görünməz bir dairə əldə etmək; dairəni hərəkət etdirmək (mərkəzin koordinatlarını dəyişdirmək). Bu obyekti ekran koordinatları şəbəkəsinə bağlamaq üçün obyekt tipini təyin etməlisiniz YER (yer), bütün həndəsi fiqurlar üçün ümumi məlumatlara sahib olacaq - obyektin ekrana bağlanmasının koordinatları X və Y:
PLACE=obyekt
X, Y: tam ədəd;
GET_X funksiyası: tam ədəd;
GET_Y funksiyası: tam ədəd;
Hər bir yeni obyekt növü əvvəlcədən müəyyən edilmiş obyekt tipinin üstündə qurula bilər ana növü Bütün sahələrin və metodların miras alındığı. Baş vermək miras, sonra obyekt növü bəyannaməsində OBYEKT mötərizədə əsas növün adı göstərilir.
Növdən istifadə YER valideyn kimi siz obyekt tipini təyin edə bilərsiniz NÖQTƏ beləliklə:
POINT=obyekt(PLACE)
V: boolean
prosedur INIT(X0, Y0: tam ədəd);
funksiya GET_V:boolean;
TURN_ON proseduru;
prosedur TURN_OFF;
6. Polimorfizm xassəsi ondan ibarətdir ki, vərəsələrin növünün bəyan edilməsində valideynin üsullarının adları ilə eyni ada malik üsullar ola bilər.
Bəyannamə növü dairə ana tip kimi istifadə olunur NÖQTƏ aşağıdakı kimi olacaq:
CIRCL=obyekt(POINT)
R: tam ədəd
prosedur INIT(X0, Y0, R0: tam ədəd); (dairə qurmaq)
TURN_ON proseduru; (görünən dairəni almaq)
prosedur TURN_OFF; (görünməz bir dairə əldə etmək)
MOVE proseduru(XN, YN: tam ədəd); (dairə hərəkəti)
GET_R funksiyası: tam ədəd; (radius almaq)
Polimorfizmdə mirasdan istifadə üsullarının müəyyən edilməsi:
CIRCL.INIT proseduru;
X:=X0; Y:=Y0;
V:=false;
prosedur CIRCL.TURN_ON;
V:=doğru;
DAİRƏ(X,Y,R);
prosedur CIRCL.TURN_OFF;
C: bayt;
C:=GetColor;
SetColor(GetBkColor); (rəngi təyin edin)
Dairə(X,Y,R);
V:=false;
SetColor(C);
prosedur CIRCL.MOVE;
F: boolean
əgər F
SÖNDÜR;
əgər F
İŞƏ SAL;
funksiya CIRCL.GET_R;
GET_R:=R;
Nəticədə, prosedurun mətni CIRCL.MOVE prosedurun mətninə uyğun gəlir POINT.MOVE, lakin bu prosedurlar üçün maşın kodları fərqli olacaq; CIRCL.MOVE icra edərkən prosedurların ünvanlarına istinad edir CIRCL.TURN_ON və CIRCL.TURN_OFF, və prosedur POINT.MOVE– prosedur ünvanlarına POINT.TURN_ON və POINT.TURN_OFF.
Erkən və gec üsulla bağlama.
Əvvəllər nəzərdən keçirilmişdir statik üsullar kompilyator onlara bütün istinadları kompilyasiya və əlaqə zamanı ayırır və həll edir ( erkən bağlama ).
Daha əvvəl təsvir edilən nümunə üçün, obyektdə CIRCLüsul irsi ola bilər HƏRƏKƏT EDİN obyektdə NÖQTƏ. Metodlar İŞƏ SAL və SÖNDÜR sonradan bağlanmaq üçün virtual elan edilməlidir.
Kompilyator kompilyasiyadan sonra virtual elan edilən metodlara həll olunmamış istinadlar buraxır. Metodda əvvəllər təsvir edilən nümunə üçün HƏRƏKƏT EDİN həll olunmamış istinadlar metod ünvanları olacaq TURN_ON, TURN_OFF, yəni prosedur HƏRƏKƏT EDİN kompilyasiyadan sonra icraya hazır olmayacaq, çünki onun maşın kodu tam müəyyən edilməmişdir.
Proqramın icrası zamanı hər hansı obyektin virtual üsulları icra edilməzdən əvvəl, konstruktor üsulu tərtibçinin həll edilməmiş istinadları TCM ilə əlaqələndirmək üçün hərəkətlər daxil etdiyi obyektin verilmiş nümunəsi üçün.
Obyekt tipli bəyannamələr YER, NÖQTƏ və CIRCL istifadə edərək konstruktor və virtual üsullar:
PLACE=obyekt
X,Y: tam ədəd;
GET_X funksiyası: tam ədəd;
GET_Y funksiyası: tam ədəd;
POINT=obyekt(PLACE)
V: boolean
konstruktor INIT(X0, Y0: tam ədəd);
GET_V funksiyası: boolean;
TURN_ON proseduru; virtual;
prosedur TURN_OFF;virtual;
MOVE proseduru(XN, YN: tam ədəd);
CIRCL=obyekt(POINT)
R: tam ədəd
konstruktor INIT(X0, Y0, R0: tam ədəd);
GET_R funksiyası: tam ədəd;
TURN_ON proseduru; virtual;
prosedur TURN_OFF; virtual;
Dağıdıcı yalnız dinamik olaraq ayrılmış obyektlər üçün lazımdır, çünki o, yaddaşı dinamik obyektdən düzgün şəkildə ayırmaq üçün obyektin faktiki ölçüsünü müəyyən edir və bu hərəkətlər dağıdıcının gövdəsində təsvir olunan hərəkətlərə əlavə olaraq standart dağıdıcı tərəfindən yerinə yetirilir.
C++ dilində bağlama
C++ proqramlaşdırma dilinin inkişafında iki əsas məqsəd yaddaşın səmərəliliyi və icra sürəti idi. Xüsusilə obyekt yönümlü tətbiqlər üçün C dilinin təkmilləşdirilməsi kimi düşünülmüşdür. C++ dilinin əsas prinsipi ondan ibarətdir ki, dilin heç bir xassəsi proqramçı tərəfindən istifadə edilmirsə, əlavə yükə (həm yaddaş, həm də sürət) səbəb olmamalıdır. Məsələn, C++-ın bütün obyekt oriyentasiyası nəzərə alınmırsa, qalanları ənənəvi C kimi sürətli işləməlidir. Buna görə də təəccüblü deyil ki, C++-da metodların əksəriyyəti dinamik (işləmə zamanı) deyil, statik olaraq bağlıdır (kompilyasiya zamanı). .
Bu dildə bağlama metodu olduqca mürəkkəbdir. Normal dəyişənlər üçün (göstəricilər və ya istinadlar deyil) statik olaraq həyata keçirilir. Lakin obyektlər göstəricilər və ya istinadlarla işarələndikdə, dinamik bağlama istifadə olunur. Sonuncu halda, statik və ya dinamik tipli metodun seçimi müvafiq metodun virtual açar sözlə elan edilib-edilməməsindən asılıdır. Əgər belə elan olunubsa, mesaj axtarış metodu dinamik sinifə, yoxsa statik sinfə əsaslanır. Dinamik bağlamanın istifadə edildiyi hallarda belə, istənilən sorğunun etibarlılığı qəbuledicinin statik sinfinə əsaslanaraq tərtibçi tərəfindən müəyyən edilir.
Məsələn, siniflərin və qlobal dəyişənlərin aşağıdakı bəyannaməsini nəzərdən keçirək: sinif Mammal
printf("danışa bilmirəm");
sinif iti: ictimai məməli
printf("wouf wouf");
printf("wouf wouf, yaxşı");
Məməli *fido = yeni İt;
fred.speak() ifadəsi "danışa bilmir"i çap edir, lakin fido->speak() çağırışı da "cant speak"ı çap edəcək, çünki Mammal sinfində müvafiq metod virtual olaraq elan olunmur. Fido->bark() ifadəsinə kompilyator tərəfindən icazə verilmir, hətta fido üçün dinamik tip Dog sinfi olsa belə. Bununla belə, statik dəyişən növü yalnız Mammal sinfidir.
Virtual sözünü əlavə etsək:
virtual boşluq danışır()
printf("danışa bilmirəm");
onda fido->speak() ifadəsi üçün gözlənilən nəticəni alırıq.
C++ dilində nisbətən yeni bir dəyişiklik obyektin dinamik sinfini tanımaq üçün vasitənin əlavə edilməsidir. Onlar RTTI (Run-Time Type Identification) sistemini təşkil edirlər.
RTTI sistemində hər bir sinif sinif haqqında müxtəlif məlumatları kodlayan əlaqəli tip məlumat strukturuna malikdir. Adı verilənlər sahəsi Bu strukturun məlumat sahələrindən birində mətn sətri kimi sinfin adı var. Typeid funksiyası verilənlərin növü haqqında məlumatları təhlil etmək üçün istifadə edilə bilər. Buna görə də, aşağıdakı əmr fido üçün "Dog" dinamik məlumat növünü çap edəcək. Bu nümunədə fido göstərici dəyişəninə istinad etmək lazımdır ki, arqument göstəricinin özü deyil, göstəricinin istinad etdiyi dəyər olsun:
cout<< «fido is a» << typeid(*fido).name() << endl;
Siz həmçinin əvvəl üzv funksiyasından istifadə edərək məlumat növü məlumatı olan bir strukturun digər struktura uyğun gələn sinfin alt sinfinə uyğun olub-olmadığını soruşa bilərsiniz. Məsələn, aşağıdakı iki ifadə doğru və yalan çıxarır:
əgər (typeid(*fido).əvvəl (typeid(fred)))…
əgər (typeid(fred).əvvəl (typeid(lassie)))…
RTTI sisteminin yaranmasından əvvəl standart proqramlaşdırma hiyləsi, sinif iyerarxiyasında nümunələr olmaq üçün metodları açıq şəkildə kodlaşdırmaq idi. Məsələn, Animal tipli dəyişənlərin qiymətinin Cat tipli və ya Dog tipli olduğunu yoxlamaq üçün aşağıdakı metodlar sistemini təyin etmək olar:
virtual int isaDog()
virtual int isaCat()
sinif iti: ictimai məməli
virtual int isaDog()
sinif Pişik: ictimai məməli
virtual int isaCat()
İndi fido-nun cari dəyərinin İt olub-olmadığını müəyyən etmək üçün fido->isaDog() istifadə edə bilərsiniz. Sıfırdan fərqli bir dəyər qaytarılırsa, onda siz dəyişən tipini istədiyiniz məlumat növünə köçürə bilərsiniz.
Tam ədəddən çox göstəricini qaytarmaqla biz alt sinifləri və tökməni birləşdiririk. Bu, RTTI sisteminin qısaca təsvir edəcəyimiz dynamic_cast adlı başqa bir hissəsinə bənzəyir. Əgər Mammal sinfindəki funksiya İt-ə göstərici qaytarırsa, o zaman Dog sinfi əvvəlcədən elan edilməlidir. Tapşırığın nəticəsi ya sıfır göstəricidir, ya da Dog sinfinə etibarlı istinaddır. Beləliklə, nəticə yoxlanışı hələ də aparılmalıdır, lakin biz yazı tipinə ehtiyacı aradan qaldırırıq. Bu, aşağıdakı nümunədə göstərilir:
sinif iti; // ilkin təsvir
virtual it* isaDog()
virtual pişik* isaCat()
sinif iti: ictimai məməli
virtual it* isaDog()
sinif Pişik: ictimai məməli
virtual pişik* isaCat()
operator lassie = fido->isaDog(); indi biz həmişə bunu edəcəyik. Nəticə olaraq, lassie dəyişəni yalnız fido dinamik Dog sinfinə malik olduqda sıfırdan fərqli qiymətə təyin edilir. Əgər fido İtə məxsus deyilsə, o zaman lassie null göstərici təyin ediləcək.
lassie = fido->isaDog();
… // fido həqiqətən İtdir
... // tapşırıq alınmadı
… // fido İt tipli deyil
Proqramçı bu üsuldan polimorfizmi geri qaytarmaq üçün istifadə edə bilsə də, bu metodun dezavantajı həm ana, həm də uşaq siniflərinə metodların əlavə edilməsini tələb etməsidir. Əgər bir çox uşaq bir ümumi valideyn sinfindən gəlirsə, üsul əlverişsiz olur. Ana sinifdə dəyişikliklərə icazə verilmirsə, bu texnika ümumiyyətlə mümkün deyil.
Bu cür problemlər tez-tez rast gəlindiyindən onlar üçün ümumi həll yolu tapıldı. Şablon funksiyası dynamic_cast şablon arqumenti kimi bir növü götürür və yuxarıda müəyyən edilmiş funksiya kimi, ya arqumentin dəyərini qaytarır (əgər yayım qanunidirsə) və ya null (əgər yayıma icazə verilmirsə). Əvvəlki misalda verilən tapşırığın ekvivalenti belə yazıla bilər:
// yalnız fido itdirsə çevirin
lassie = dinamik_cast< Dog* >(fido);
// sonra aktyor heyətinin uğurlu olub olmadığını yoxlayın
C++ dilinə daha üç cast növü (static_cast, const_cast və reinterpret_cast) əlavə edildi, lakin onlar xüsusi hallarda istifadə olunur və buna görə də burada təsvir edilmir. Proqramçılar onları köhnə tip tökmə mexanizmi əvəzinə daha təhlükəsiz vasitə kimi istifadə etməyə təşviq edilir.
2. Dizayn hissəsi
Bu paraqraf, qısalığına baxmayaraq, çox vacibdir - demək olar ki, hamısı peşəkardır proqramlaşdırma Java-da polimorfizmin istifadəsinə əsaslanır. Eyni zamanda, bu mövzu tələbələrin başa düşdüyü ən çətin mövzulardan biridir. Buna görə də, bu paraqrafı bir neçə dəfə diqqətlə oxumağınız tövsiyə olunur.
Sinif metodları təsadüfən statik dəyişdirici ilə qeyd olunur - onlar üçün proqram kodunu tərtib edərkən, statik əlaqə. Bu o deməkdir ki, mənbə kodunda metod adı hansı sinifin kontekstində göstərilibsə, tərtib edilmiş kodda həmin sinfin metoduna istinad edilir. Yəni həyata keçirilir metod adının bağlanması zəng saytında icra edilə bilən kod ilə bu üsul. Bəzən statik əlaqəçağırdı erkən bağlama, proqramın tərtib mərhələsində baş verdiyi üçün. Statik əlaqə Java-da daha bir halda istifadə olunur - sinif son dəyişdirici ilə elan edildikdə ("final", "final").
Java-da obyekt metodları dinamikdir, yəni tabedir dinamik bağlama. Proqramın icrası mərhələsində bilavasitə metod çağırışı zamanı baş verir və bu metodun yazılması mərhələsində çağırışın hansı sinifdən ediləcəyi əvvəlcədən məlum deyil. Bu, bu kodun işlədiyi obyektin növü ilə müəyyən edilir - obyektin hansı sinfə aid olması, metodun həmin sinifdən çağırılması. Bu bağlama metod kodunun tərtib edildiyi vaxtdan çox gec baş verir. Buna görə də, bu cür bağlama çox vaxt adlanır gec bağlama.
Zəng əsaslı kod dinamik üsullar, mülkü var polimorfizm- eyni kod hansı növ obyektin onu çağırmasından asılı olaraq fərqli işləyir, lakin metodun mənbə kodu ilə əlaqəli abstraksiya səviyyəsində eyni şeyi edir.
Birinci oxunuşda o qədər də aydın olmayan bu sözləri aydınlaşdırmaq üçün əvvəlki paraqrafdakı nümunəni - moveTo metodunun işləməsini nəzərdən keçirək. Təcrübəsiz proqramçılara elə gəlir ki, bu metodu hər bir törəmə sinifdə ləğv etmək lazımdır. Bu, həqiqətən edilə bilər və hər şey düzgün işləyəcək. Ancaq belə kod son dərəcə lazımsız olacaq - axı, metodun tətbiqi bütün nəsil siniflərində olacaq rəqəm tamamilə eyni:
public void moveTo(int x, int y)( hide(); this.x=x; this.y=y; show(); );
Həm də polimorfizmdən istifadə etmir. Beləliklə, biz bunu etməyəcəyik.
Çox vaxt niyə sual yaranır abstrakt sinif rəqəm bu metodun tətbiqini yazın. Axı, burada istifadə edilən gizlət və göstər metodu çağırışları ilk baxışdan zənglər olmalıdır mücərrəd üsullar- yəni, deyəsən, heç işləyə bilmirlər!
Lakin gizlət və göstər üsulları dinamikdir, bu, artıq bildiyimiz kimi, metodun adının və onun icra olunan kodunun bağlanmasının iş vaxtında həyata keçirildiyini bildirir. Buna görə də, bu üsulların sinif kontekstində dəqiqləşdirilməsi rəqəm, ümumiyyətlə sinifdən çağırılacaqları demək deyil rəqəm! Bundan əlavə, gizlət və göstər metodlarının heç vaxt bu sinifdən çağırılmayacağına zəmanət verə bilərsiniz. Tutaq ki, Dot tipli dot1 və Circle tipli dairə1 dəyişənlərimiz var və onlara müvafiq tiplərin obyekt istinadları təyin olunub. Gəlin görək dot1.moveTo(x1,y1) və circle1.moveTo(x2,y2) çağırışları necə davranır.
dot1.moveTo(x1,y1) çağırıldıqda sinifdən zəng edilir rəqəm köçürmə üsulu. Həqiqətən də, Dot sinifindəki bu üsul ləğv edilmir, yəni ondan miras qalmışdır rəqəm. MoveTo metodunda ilk ifadə dinamik gizlətmə metoduna çağırışdır. Bu metodun həyata keçirilməsi bu metodu çağıran dot1 obyektinin nümunə olduğu sinifdən götürülür. Yəni Dot sinfindən. Beləliklə, məqam gizlədilir. Sonra obyektin koordinatlarında dəyişiklik olur, bundan sonra o, çağırılır dinamik üsul göstərmək. Bu metodun həyata keçirilməsi bu metodu çağıran dot1 obyektinin nümunə olduğu sinifdən götürülür. Yəni Dot sinfindən. Beləliklə, yeni yerdə bir nöqtə göstərilir.
circle1.moveTo(x2,y2)-ə zəng etmək üçün hər şey tam eynidir - dinamik gizlət və göstər metodları circuit1 obyektinin nümunəsi olduğu sinifdən, yəni Circle sinfindən çağırılır. Beləliklə, dairə köhnə yerdə gizlənir və yeni yerdə göstərilir.
Yəni obyekt nöqtədirsə, nöqtə hərəkət edir. Əgər obyekt dairədirsə, dairə hərəkət edir. Üstəlik, əgər nə vaxtsa kimsə, məsələn, Circle-dan miras qalan və obyekt yaradan Ellips sinfi yazırsa. Ellips ellips=yeni Ellips(…), sonra ellipse.moveTo(…) çağırmaq ellipsdə yeni yerə keçəcək. Və bu, Ellips sinfində gizlət və göstər üsullarının necə həyata keçirildiyinə uyğun olaraq baş verəcəkdir. Qeyd edək ki, sinfin tərtib edilmiş polimorfik kodu çoxdan işləyəcək rəqəm. Polimorfizm, tərtib zamanı bu metodlara istinadların moveTo metodunun koduna daxil edilməməsi ilə təmin edilir - onlar moveTo metodu olduğu anda çağıran obyektin sinfindən belə adlarla metodlara təyin olunur. çağırdı.
Obyekt yönümlü proqramlaşdırma dillərində iki növ vardır dinamik üsullar- əslində dinamik və virtual. Fəaliyyət prinsipinə görə, onlar tamamilə oxşardırlar və yalnız icra xüsusiyyətləri ilə fərqlənirlər. Zəng edin virtual üsullar Daha sürətli. Dinamik daha yavaş çağırılır, lakin xidmət masası dinamik üsullar(DMT - Dinamik Metodlar Cədvəli) cədvəldən bir qədər az yaddaş tutur virtual üsullar(VMT - Virtual Metodlar Cədvəli).
Bu bir problem kimi görünə bilər dinamik üsullar uzun ad axtarışlarına görə vaxt sərfəli deyil. Əslində, zəng zamanı heç bir ad axtarışı aparılmır, lakin qeyd olunan virtual (dinamik) üsullar cədvəlindən istifadə edərək, daha sürətli mexanizmdən istifadə edilir. Lakin biz bu cədvəllərin tətbiqi xüsusiyyətləri üzərində dayanmayacağıq, çünki Java bu tip metodlar arasında fərq qoymur.
6.8. Əsas sinif Obyekt
Obyekt sinfi bütün Java sinifləri üçün əsas sinifdir. Buna görə də onun bütün sahələri və metodları miras alınır və bütün siniflərdə yer alır. Obyekt sinfi aşağıdakı metodları ehtiva edir:
- ictimai Boole bərabərdir(Obyekt obyekti)– metodun çağırıldığı obyektin və parametrlər siyahısında obj istinadından keçən obyektin dəyərləri bərabər olarsa, doğru qaytarır. Obyektlər bərabər deyilsə, false qaytarılır. Obyekt sinfində bərabərlik istinad bərabərliyi kimi qəbul edilir və "==" müqayisə operatoruna ekvivalentdir. Ancaq nəsillərdə bu üsul ləğv edilə bilər və obyektləri məzmununa görə müqayisə edə bilər. Məsələn, bu, sarğı rəqəmli sinif obyektləri üçün baş verir. Bunu bu kodla yoxlamaq asandır:
İkiqat d1=1.0,d2=1.0; System.out.println("d1==d2 ="+(d1==d2)); System.out.println("d1.equals(d2) ="+(d1.equals(d2)));
İlk çıxış sətri d1==d2 =false, ikincisi isə d1 verəcək. bərabərdir(d2)=doğrudur
- public int hashCode()- məsələlər hash kodu obyekt. Hash kodu elementlə əlaqəli şərti olaraq unikal rəqəmli identifikatordur. Təhlükəsizlik səbəbi ilə siz tətbiq proqramına obyektin ünvanını verə bilməzsiniz. Buna görə də Java-da hansısa məqsəd üçün obyekt ünvanlarının cədvəllərinin saxlanmalı olduğu hallarda hash kodu obyektin ünvanını əvəz edir.
- qorunan obyekt klonu() CloneNotSupportedException atır - metod obyekti kopyalayır və obyektin yaradılmış klonuna (dublikatına) keçid qaytarır. Obyekt sinfinin varislərində o, ləğv edilməli və həmçinin sinfin Clonable interfeysini həyata keçirdiyini göstərməlidir. Klonlaşdırmanı dəstəkləməyən obyektdən metodu çağırmağa cəhd səbəb olur istisna atmaq CloneNotSupportedException ("Klonlaşdırma dəstəklənmir"). İnterfeyslər və istisnalar daha sonra müzakirə olunacaq.
Klonlaşdırmanın iki növü var: dayaz (dayaz), orijinal obyektin sahələrinin dəyərləri klona bir-bir kopyalandıqda və sahələr üçün yeni obyektlərin yaradıldığı dərin (dərin). orijinalın sahələri ilə istinad edilən obyektlərin klonlaşdırılması. Dayaz klonlama ilə həm orijinal, həm də klon eyni obyektlərə istinad edəcək. Obyektdə yalnız sahələr varsa primitiv növlər, dayaz və dərin klonlama arasında heç bir fərq yoxdur. Klonlaşdırma sinfi inkişaf etdirən proqramçı tərəfindən həyata keçirilir, avtomatik klonlama mexanizmi yoxdur. Və hansı klonlama variantını seçəcəyinizə məhz sinifin inkişaf mərhələsində qərar verməlisiniz. Əksər hallarda bu tələb olunur dərin klonlaşdırma.
- ictimai yekun Class getClass()– sinif tipli meta-obyektə istinad qaytarır. Onunla siz obyektin aid olduğu sinif haqqında məlumat əldə edə və onun sinif metodlarını və sinif sahələrini çağıra bilərsiniz.
- qorunan void finalize() throws Throwable - obyekt məhv edilməzdən əvvəl çağırılır. Obyekti məhv etməzdən əvvəl bəzi köməkçi hərəkətləri yerinə yetirməli olan Obyektin nəsillərində ləğv edilməlidir (faylı bağlamaq, mesaj göstərmək, ekranda nəsə çəkmək və s.). Bu üsul haqqında daha çox məlumat müvafiq paraqrafda təsvir edilmişdir.
- ictimai String toString()- obyektin simli təsvirini qaytarır (mümkün qədər adekvat). Obyekt sinfində bu üsul obyektin tam uyğun adını (paket adı ilə) sətirdə çap edir, ardınca "@" simvolu, sonra isə obyektin hash kodunu onaltılıq sistemdə çap edir. Əksər standart siniflər bu metodu ləğv edir. Rəqəmli siniflər üçün nömrənin sətir təsviri, sətir sinifləri üçün sətirin məzmunu, simvol sinifləri üçün simvolun özü (və onun kodunun sətir təsviri deyil!) qaytarılır. Məsələn, aşağıdakı kod parçası
Obyekt obyekti=yeni Obyekt(); System.out.println(" obj.toString() "+obj.toString() verir); Cüt d=yeni Double(1.0); System.out.println(" d.toString() "+d.toString() verir); c="A" simvolu; System.out.println("c.toString() "+c.toString() verir);
nəticə çıxaracaq
obj.toString() verir [email protected] d.toString() 1.0 c verir.toString() A verir
üsulları da var bildir(), notifyAll(), və metodun bir neçə həddən artıq yüklənmiş variantları Gözləmək, iplərlə işləmək üçün nəzərdə tutulmuşdur. Onlar mövzular bölməsində müzakirə olunur.
6.9. Konstruktorlar. Qorunan sözlər super və bu. Başlanğıc blokları
Artıq qeyd edildiyi kimi, Java-da obyektlər qorunan sözdən istifadə edərək yaradılır new , ondan sonra konstruktor gəlir - obyekti yaradan və yaradılmış obyektin sahələrini işə salan xüsusi alt proqram. O, qaytarma növünü göstərmir və o, nə obyekt metodudur (obyekt hələ mövcud olmadıqda sinif adı ilə çağırılır), nə də sinif metodudur (obyekt və onun sahələri bu istinad vasitəsilə konstruktorda mövcuddur) . Əslində konstruktor yeni operatorla birlikdə yaradılan obyektə istinadı qaytarır və sinif metodlarının və obyekt metodlarının xüsusiyyətlərini birləşdirən xüsusi növ metod hesab edilə bilər.
Obyekt yaradılarkən heç bir əlavə başlanğıc tələb etmirsə, siz hər bir sinif üçün standart olaraq mövcud olan konstruktordan istifadə edə bilərsiniz. Bu boş mötərizələrdən sonra sinfin adıdır - parametr siyahısı yoxdur. Sinif hazırlayarkən belə konstruktorun göstərilməsinə ehtiyac yoxdur, o, avtomatik olaraq mövcuddur.
İnisializasiya tələb olunarsa, adətən parametrlər siyahısı olan konstruktorlardan istifadə olunur. Dot və Circle sinifləri üçün belə konstruktorların nümunələrini gördük. Dot və Circle sinifləri miras qalmışdır abstrakt siniflər, heç bir konstruktoru olmayan. Mücərrəd olmayan sinifdən, yəni artıq konstruktoru olan sinifdən miras varsa (defolt konstruktor olsa belə) bəzi xüsusiyyətlər yaranır. Konstruktorda ilk ifadə superclass konstruktoruna çağırış olmalıdır. Amma bu sinfin adı ilə deyil, qorunan sözün köməyi ilə edilir super(" superclass "-dan), ardınca ana konstruktor üçün tələb olunan parametrlərin siyahısı. Bu konstruktor supersinifdən (bütün əvvəlki nənə və babalar daxil olmaqla) miras qalan məlumat sahələrini işə salır. Məsələn, FilledCircle sinfini yazaq - Circle-ın varisi, onun nümunəsi rəngli dairə kimi çəkiləcək.
java_gui_example paketi; java.awt.* idxal edin; ictimai sinif FilledCircle Circle genişləndirir( /** FilledCircle-ın yeni nümunəsini yaradır */ public FilledCircle(Graphics g,Color bgColor, int r,Color color) ( super(g,bgColor,r); this.color=color; ) public void show()( Color oldC=graphics.getColor(); graphics.setColor(color); graphics.setXORMode(bgColor); graphics.fillOval(x,y,size,size); graphics.setColor(oldC); qrafik. setPaintMode(); ) public void hide()( Rəng oldC=graphics.getColor(); graphics.setColor(color); graphics.setXORMode(bgColor); graphics.fillOval(x,y,size,size); graphics.setColor (köhnəC); graphics.setPaintMode(); ))
Ümumiyyətlə, mürəkkəb obyektlərin yaradılmasının məntiqi: obyektin əsas hissəsi ilk növbədə Object sinfindən miras qalmış hissədən başlayaraq, daha sonra isə iyerarxiya boyunca sinfin özünə aid olan hissə ilə bitərək yaradılır və işə salınır. Buna görə konstruktorun ilk ifadəsi adətən super ana konstruktora ( parametr siyahısı), çünki əsas sinif tərəfindən qorunan obyektin işə salınmamış hissəsinə daxil olmaq gözlənilməz nəticələrə səbəb ola bilər.
Bu sinifdə biz əvvəlki dərslərlə müqayisədə fiqurları çəkmək və “gizlətmək” üçün daha təkmil üsuldan istifadə edirik. O, XOR (“eksklüziv və ya”) rəsm rejimindən istifadəyə əsaslanır. Bu rejim setXORMode metodundan istifadə etməklə qurulur. Bu zaman fiqurun eyni yerə təkrar çəkilməsi çıxış sahəsində orijinal təsvirin bərpasına gətirib çıxarır. Normal rəsm rejiminə keçid setPaintMode metodu ilə həyata keçirilir.
Tez-tez konstruktorlarda istifadə olunur