At kalde en tilsidesættes metode, superklasse et opkald tilsidesættes metode

Denne kode kaster en undtagelse, AttributeError, “wtf!”, fordi A.foo() ringer B.foo1(), skulle det ikke ringe A.foo1()? Hvordan kan jeg tvinge den til at ringe A.foo1() (og alle metode kald inde A.foo() skal ringe A.*)

class A(object):
    def foo(self):
        print self.foo1()

    def foo1(self):
        return "foo"

class B(A):
    def foo1(self):
        raise AttributeError, "wtf!"

    def foo(self):
        raise AttributeError, "wtf!"

    def foo2(self):
        super(B, self).foo()

myB = B()
myB.foo2()
Du er dybest set spørger til Python smide dynamicness og virtuelle metoder og jeg på en eller anden måde, finde ud af at springe dele af attribut opslag kæde er baseret på, hvor funktionen er leksikalsk defineret. Ikke kommer til at ske.
Jeg tror, at dette er en indikator af dårligt design. Hvis du har tilsidesat en metode i din underklasse, men du ikke vil have det til at hedde, er det ikke et tegn på, at du gjorde noget forkert? Jeg tror, du bør genoverveje din klasse hierarki – måske B bør ikke være en underklasse af A.

OriginalForfatteren Perico de los palotes | 2011-10-22

4 svar

  1. 6

    I klasse A i stedet for at kalde self metoder, du har brug for at ringe til A metoder og passere i self manuelt.

    Dette er ikke den normale måde at gøre tingene på-du bør have en virkelig god grund til at gøre det på denne måde.

    class A(object):
        def foo(self):
            print A.foo1(self)
    
        def foo1(self):
            return "foo"
    
    class B(A):
        def foo1(self):
            raise AttributeError, "wtf!"
    
        def foo(self):
            raise AttributeError, "wtf!"
    
        def foo2(self):
            super(B, self).foo()
    
    myB = B()
    myB.foo2()

    OriginalForfatteren Ethan Furman

  2. 6

    Det virker efter hensigten, som 100% af verden programmeringssprog arbejde. Underklasse tilsidesætter ALLE metoder forælder klasse.

    Men hvis du virkelig, virkelig ønsker at kalde A. foo1() du kan være i stand til at gøre det som denne (jeg kan ikke garantere). Og under alle omstændigheder skal du ikke gøre dette, da dette er mod alle principper for god planlægning.

     class A(object):
    
        def foo(self):
            A.foo1(self)

    OriginalForfatteren Mikko Ohtamaa

  3. 3

    I koden:

    def foo2(self):
        super(B, self).foo()

    selv er en instans af B.

    Når en metode, der stammer fra En kaldes af en instans af B vil det begynde at kigge i namespace fra B, og kun hvis den metode er ikke fundet (fx er der ikke tilsidesættes af B) gennemførelse fra En bruges, men altid med selv at henvise til B. På intet tidspunkt selv er et eksempel på A.

    OriginalForfatteren extraneon

  4. -1

    Man kan se, hvad Python er at gøre her, men den måde, der tilsidesætter er en smule ekstrem. Tage det tilfælde, hvor klasse A definerer 100 attributter og klasse B arver disse og tilføje 1 mere attribut. Vi ønsker at være i stand til at have __init__() for B kalde __init__() for A, og lad B ‘ s kode, der definerer kun den enkelte attribut. Tilsvarende, hvis vi definerer en reset () – metoden i En for at indstille alle attributter til nul, og derefter tilsvarende reset() metode til B skal være i stand til bare at kalde reset () – metoden for En og så nul ud for enkelt B-attributten i stedet for at skulle til at kopiere alle af En kode. Python er svært at gøre, hvad der formodes at være en stor fordel for objekt-orienteret programmering; der er, genbrug af kode. Den bedste løsning her er at undgå at tilsidesættelse af metoder, som vi virkelig ønsker at genbruge. Hvis du ønsker at få en fornemmelse af komplikationer med Python her, så prøv denne kode:

    class X(object):
        def __init__ ( self ):
            print "X"
            self.x = 'x'
            self.reset()
            print "back to X"
        def reset ( self ):
            print "reset X"
            self.xx = 'xx'
    
    class Y(X):
        def __init__ ( self ):
            print "Y"
            super(Y,self).__init__()
            self.y = 'y'
            self.reset()
            print "back to Y"
        def reset ( self ):
            print "reset Y"
            super(Y,self).reset()
            print "back to reset Y"
            self.yy = 'yy'
    
    aY = Y()

    (For at gøre dette arbejde ordentligt, fjerner du den selv.reset () – kald i __init__() for klasse Y.)

    OriginalForfatteren Clinton Mah

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *