2016-10-18 1 views
1

Ich habe eine Klasse Dokument, diese Klasse ist wirklich komplex zu instanziieren, so dass ich ein Builder-Objekt habe, um sie zu erstellen. Beide Elemente gehören nicht mir, also kann ich sie nicht ändernWie erben Sie von einer Klasse, die mit einem Builder instanziiert wurde?

Jetzt möchte ich eine Unterklasse des Dokuments erstellen, nur um einige spezifische Methoden hinzuzufügen. Um die vorgesehenen Builder zu weiterverwenden habe ich versucht, dies:

class SpecialDocument(Document): 
    def __new__(cls, *args): 
     return DocumentBuilder(*args) 

    def __init__(self, *args, **kwargs): 
     #My initialization 

Das Problem hierbei ist, dass die __init__ Methode führt nie die __new__ Verfahren verursachen nicht wieder ein SpecialDocument (Es gibt einen Document)

In In meinem speziellen Fall muss ich meine SpecialDocument nicht anders bauen, als ich eine Document baue. Gibt es eine Möglichkeit, denselben Builder zu verwenden? Wenn nicht, wie kann ich das erreichen? Ich möchte einfach von Document erben, um bestimmte Funktionalitäten hinzuzufügen, vielleicht könnte es mit Metaklassen erreicht werden, aber ich habe sie nie benutzt (wahrscheinlich weil ich es nicht vollständig verstehe), ein kleiner Einblick wäre schön, wenn es mir helfen könnte Problem

+0

Brauchen Sie wirklich eine * Unterklasse *? Können Sie nicht einfach Delegierung verwenden, um nur das gewünschte Verhalten hinzuzufügen? – Bakuriu

+0

Was ist die Beziehung zwischen 'Document' und' DocumentBuilder'? –

+0

@PhilipTzou 'DocumentBuilder' ist eine unabhängige Klasse, die ein neues' Document' -Objekt zurückgibt, wenn es ohne Parameter konstruiert ist oder dessen Variablen initialisiert, wenn es einen Parameter empfängt (Der Parameter ist ein Pfad zum tatsächlichen Dokument, falls vorhanden) –

Antwort

1

Sie brauchen eigentlich keine Metaklasse hier - Sie müssen nur die Superklasse '__new__ Methode aufrufen. So wie Sie es tun, "weiß" die Instanziierung der Oberklasse nicht, dass sie überhaupt von einer Unterklasse aufgerufen wird.

Also, schreiben Sie einfach Ihren Code wie folgt statt:

class SpecialDocument(Document): 
    def __new__(cls, *args): 
     return super().__new__(cls, *args) 

    def __init__(self, *args, **kwargs): 
     #My initialization 

Nun, dass der gewöhnliche Weg, es zu tun - und würde funktionieren, wenn der Code in Ihrem „Builder“ -Funktion richtig in Docment des getätigt __new__ oder __init__.
Da der Code dies nicht tut und Sie Ihre Unterklasse nicht als Parameter an den Builder übergeben können, könnte es eine funktionierende Lösung sein, ein normales Dokument zu erstellen und seine Klasse zu ersetzen, nachdem sie erstellt wurde:

def special_document_init(special_document): 
    ... 

class SpecialDocument(Document): 
    def my_special_method(self, ...): 
     ... 
    def overriden_method(self): 
     ... 
     result = super().overriden_method() 
     ... 

def build_special_document(*args): 
    document = DocumentBuilder(*args) 
    document.__class__ = SpecialDocument 
    special_document_init(document) 
    return document 
Verwandte Themen