Programim dhe zhvillim, javascript, python, php, html

Pse ripërdorimi i identifikuesit nuk hyn në fuqi nëse një anëtar thirret nga një objekt i përditësuar? [dublika]

class Program
{
    static void Main(string[] args)
    {
        Parent p = new Child();
        p.Print();
    }
}
class Parent
{
    public virtual void Print()
    {
        Console.WriteLine("This is parent.");
    }
}
class Kid:Parent
{
    public override void Print()
    {
        Console.WriteLine("This is Kid.");
    }
}
class Child : Kid
{
    public new virtual void Print()
    {
        Console.WriteLine("This is Child.");
    }
}  

Pse dalja është "This is Kid" dhe jo "This is child"?

Print() në klasën Child është virtuale.
Po përpiqem të kuptoj se çfarë po ndodh.

14.08.2012

  • Pyetja juaj (Çfarë bëjnë ata) nuk përputhet me titullin (Si funksionon). Por të dyja janë (shumë herë) dublikatë. Dhe ju jeni të paqartë për çfarë nuk kuptoni. 14.08.2012
  • @user1559463 Unë kam redaktuar titullin e pyetjes suaj. Tani përshtatet më mirë me temën tuaj. 14.08.2012

Përgjigjet:


1

Ju po telefononi metodën e anashkaluar PrintParent.

Operatori new do të funksionojë nëse e shkruani atë variabël si Kid. Në këtë rast, new nuk është një anulim, por një ripërdorim identifikues.

14.08.2012
  • Fëmijë p = fëmijë i ri(); ende më jep Ky është fëmijë. 14.08.2012
  • @user1559463 Kontrollo dy herë përgjigjen time. Nëse nuk shkruani variablin tuaj si Child, nuk do të merrni This is Child. A nuk e kuptoni se operatori new nuk është ekuivalent me metodat mbizotëruese? 14.08.2012

  • 2

    p është i tipit Parent. Pra, përpiluesi kërkon një metodë Print në klasën Parent. Duke qenë se kjo metodë është virtuale, ajo gjen një metodë të anashkaluar në klasën Kid. Për shkak se ju nuk e keni zëvendësuar, por zëvendësuar metodën PrintChild, përpiluesi nuk e përdor këtë metodë.

    14.08.2012
  • Përpiluesi sheh se lloji është Parent, dhe lloji me pikë është Fëmijë? atëherë ai gjen metodën virtuale dhe sheh që Pointer po tregon një lloj tjetër, pra ai po kërkon një metodë që kapërceu metodën aktuale? nëse nuk e gjen, do të përdorë metodën në Prind? 14.08.2012
  • @user1559463 Përpiluesi sheh që lloji i ndryshores është Parent dhe për këtë arsye përpiqet të thërrasë metodën Print të tipit Parent. Nëse metoda juaj në nuk ishte virtuale, programi juaj do të shfaqte This is prind. Por meqenëse është virtuale, përpiluesi kërkon metoda mbizotëruese dhe thërret zëvendësimin më specifik - që është në Kid. Kjo për shkak se zinxhiri juaj i mbivendosjes ndalon në Kid sepse keni përdorur fjalën kyçe new për metodën tuaj Child.Print(). 14.08.2012
  • @user1559463 Nëse dëshironi të shfaqni This is Child, duhet të zëvendësoni new virtual me një override tjetër për t'i thënë kompajlerit se kjo metodë është një version më specifik i metodës së trashëguar nga Kid ose Parent, dhe jo një version krejtësisht i ri. 14.08.2012

  • 3

    Epo, sepse keni përdorur fjalën kyçe të re, do të thotë që keni fshehur metodën e trashëguar dhe keni ofruar një zbatim të ri. Kjo zakonisht quhet si fshehje e anëtarëve prindërorë.

    14.08.2012

    4

    Nga MSDN ( http://msdn.microsoft.com/en-us/library/6fawty39(v=vs.100).aspx ):

    "Kur DoWork thirret në një shembull të Derived, përpiluesi C# së pari do të përpiqet ta bëjë thirrjen të pajtueshme me versionet e DoWork të deklaruara fillimisht në Derived. Metodat e mbivendosjes nuk konsiderohen si të deklaruara në një klasë, ato janë zbatime të reja të një metode deklaruar në një klasë bazë Vetëm nëse përpiluesi C# nuk mund të përputhet me thirrjen e metodës me një metodë origjinale në Derived do të përpiqet të përputhet me një metodë të tejkaluar me të njëjtin emër dhe parametra të pajtueshëm."

    Duket sikur përdorimi juaj i 'new' në Kid, por deklarimi i p si Prind do të thotë që p nuk mund ta shohë Printin në Fëmijë pasi nuk është pjesë e hierarkisë së trashëgimisë.

    static void Main(string[] args)
    {
        Parent p = new Child();
        p.Print();
    
        Child c = (Child) p;
        c.Print();
    }
    

    ... padyshim që ndryshon gjërat.

    14.08.2012

    5

    Më poshtë e thjeshton dhe trajton një zbatim të mundshëm si fakt, por duhet të mjaftojë për të pasur një model mendor funksional.

    Kur telefononi kodin "di për" një klasë, ai di gjërat e mëposhtme:

    1. Fushat mund të aksesohen në një zhvendosje të veçantë nga vendndodhja e objektit. Kështu, për shembull, nëse një objekt është në adresën 120 dhe ka dy fusha me numra të plotë, atëherë ai mund të jetë në gjendje t'i qaset njërës në adresën 124. Nëse një objekt tjetër i të njëjtit lloj ishte në adresën 140, fusha ekuivalente do të ishte në 144.

    2. Metodat jo virtuale (dhe vetitë mund të konsiderohen sheqer sintaksor në një ose dy metoda) janë funksione në një adresë të caktuar që marrin një referencë për objektin që po thërrisni (this nga brenda metodës) dhe parametrat e tjerë të atij funksioni.

    3. Metodat virtuale janë si më sipër, por adresa e tyre mund të gjendet duke parë një zhvendosje të veçantë brenda një tabele të lidhur me klasën, adresa e së cilës do të jetë gjithashtu një zhvendosje e veçantë nga adresa e klasës.

    Në këtë, Kid ka një tabelë metodash që është një superbashkësi e asaj të Parent (mund të shtojë më shumë metoda), dhe e cila ka të njëjtën adresë funksioni për ato metoda që nuk i ka kaluar (duke thirrur Equals në të përdor të njëjtën funksionon si thirrja e Equals në një Parent), por një adresë e ndryshme për ata që i kalon (Print() në këtë rast).

    Prandaj, nëse keni një Kid, atëherë nëse e keni atë nëpërmjet referencës Parent ose Kid, thirrja e Print() do të shikojë në të njëjtën tabelë, do të kërkojë vendndodhjen e metodës Print() dhe do ta thërrasë atë.

    Në rastin e Child, përdoret new në metodën Print. Kjo i tregon përpiluesit se ne duam në mënyrë specifike një tabelë të ndryshme. Prandaj, nëse thërrasim Print() nëpërmjet referencës Child, ai kërkon tabelën specifike të Child dhe thërret metodën që gjen. Nëse sidoqoftë e quajmë atë nëpërmjet referencës Kid ose Parent, atëherë as nuk e dimë se ekziston një tabelë specifike e Child që mund të përdorim dhe ne kërkojmë funksionin në tabelën që dimë se Kid dhe Parent kanë përkatësisht, dhe thërrasim funksioni i gjetur (ai i përcaktuar në Kid).

    Si rregull, new duhet të shmanget. Përdorimi i tij është në dy vende:

    Njëra është përputhshmëria e prapambetur. Nëse për shembull Child kishte një pronë Name, dhe më vonë kodi për Parent u ndryshua në mënyrë që edhe ai të kishte një pronë Name, ne kemi një konflikt. Meqenëse Name i Child nuk është një ndryshim, ai trajtohet sikur të kishte new, por na jep një paralajmërim, pasi kjo është e vetmja mënyrë që kodi që përdor mënyrën e vjetër të gjërave dhe kodin që di për Name të ri në Parent mund të bashkëekzistojë. . Nëse kthehemi ndonjëherë për të ripërpiluar Child, ndoshta duhet të rifaktorojmë në mënyrë që ai të mos ketë Name-në e vet (nëse ai më Parent bën atë që duam ne), të rifaktorojmë kështu që është një zëvendësim, rifaktor i diçkaje krejtësisht të ndryshme, ose të shtojmë new për të treguar se kështu duam që gjërat të jenë pavarësisht se është më pak se ideale.

    Tjetra është kur new lejon një formë më specifike të së njëjtës sjellje që lejon metoda e klasës bazë, por është logjikisht e pajtueshme (kështu që përdoruesit të mos habiten). Kjo e fundit duhet të hyjë në kutinë e teknikave gjysmë të avancuara dhe të mos bëhet lehtë. Gjithashtu duhet komentuar si e tillë, sepse në shumicën e rasteve të shohësh new do të thotë të merresh me diçka që në rastin më të mirë është një kompromis dhe ndoshta duhet përmirësuar.

    (Përveç: a jam unë i vetmi person që mendova për gazetat tabloide kur pashë Kids që kishte Children?)

    14.08.2012
    Materiale të reja

    Masterclass Coroutines: Kapitulli-3: Anulimi i korutinave dhe trajtimi i përjashtimeve.
    Mirë se vini në udhëzuesin gjithëpërfshirës mbi Kotlin Coroutines! Në këtë seri artikujsh, unë do t'ju çoj në një udhëtim magjepsës, duke filluar nga bazat dhe gradualisht duke u thelluar në..

    Faketojeni derisa ta arrini me të dhënat false
    A e gjeni ndonjëherë veten duke ndërtuar një aplikacion të ri dhe keni nevojë për të dhëna testimi që duken dhe duken më realiste ose një grup i madh të dhënash për performancën e ngarkesës...

    Si të përdorni kërkesën API në Python
    Kërkesë API në GitHub për të marrë depot e përdoruesve duke përdorur Python. Në këtë artikull, unë shpjegoj procesin hap pas hapi për të trajtuar një kërkesë API për të marrë të dhëna nga..

    Një udhëzues hap pas hapi për të zotëruar React
    Në këtë artikull, do të mësoni se si të krijoni aplikacionin React, do të mësoni se si funksionon React dhe konceptet thelbësore që duhet të dini për të ndërtuar aplikacione React. Learning..

    AI dhe Psikologjia — Pjesa 2
    Në pjesën 2 të serisë sonë të AI dhe Psikologji ne diskutojmë se si makineritë mbledhin dhe përpunojnë të dhëna për të mësuar emocione dhe ndjenja të ndryshme në mendjen e njeriut, duke ndihmuar..

    Esencialet e punës ditore të kodit tim VS
    Shtesat e mia të preferuara - Git Graph 💹 Kjo shtesë është vërtet e mahnitshme, e përdor përpara se të filloj të punoj për të kontrolluar dy herë ndryshimet dhe degët më të fundit, mund të..

    Pse Python? Zbulimi i fuqisë së gjithanshme të një gjiganti programues
    Në peizazhin gjithnjë në zhvillim të gjuhëve të programimit, Python është shfaqur si një forcë dominuese. Rritja e tij meteorike nuk është rastësi. Joshja e Python qëndron në thjeshtësinë,..