2016-10-18 2 views
1

У меня есть документ класса, этот класс действительно сложный для создания экземпляра, поэтому у меня есть объект-строитель для их создания. Оба элемента не мои, поэтому я не могу их изменитьКак наследовать от класса, созданного с помощью построителя?

Теперь я хочу создать подкласс документа, просто чтобы добавить некоторые конкретные методы. Для того, чтобы продолжать использовать предоставленный строитель Я попытался это:

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

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

Проблема здесь состоит в том, что метод __init__ никогда не выполняет вызвать метод __new__ не возвращает SpecialDocument (Он возвращает Document)

В в моем конкретном случае мне не нужно строить мой SpecialDocument по-другому от того, как я строю Document. Есть ли способ использовать один и тот же построитель? Если нет, как я могу это достичь? Я просто хочу унаследовать от Document, чтобы добавить определенные функции, возможно, это может быть достигнуто с помощью метаклассов, но я никогда не использовал их (возможно, потому что я не совсем понимаю это), немного проницательность для них была бы хорошей, если бы она помогла решить мои проблема

+0

Вам действительно нужен подкласс *? Не можете ли вы просто использовать делегирование только для добавления поведения, которое вы хотите? – Bakuriu

+0

Какая связь между 'Document' и' DocumentBuilder'? –

+0

@PhilipTzou 'DocumentBuilder' является независимым классом, который возвращает новый объект Document, если он сконструирован без параметров или инициирует его переменные, если он получает параметр (параметр - путь к фактическому документу, если он существует) –

ответ

1

Вам действительно не нужен метакласс здесь - вам просто нужно вызвать суперкласс «__new__». Как вы это делаете, создание суперкласса не «знает», что оно вызывается из подкласса вообще.

Таким образом, просто написать код, как это вместо:

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

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

Теперь, это обычный способ сделать это - и будет работать, если код в функции «строитель» был правильно установлен внутри Docment-х __new__ или __init__.
Поскольку код там не работает, и вы можете [t передать ваш подкласс в качестве параметра для строителя, рабочим решением может быть создание обычного документа и замена его класса после его создания:

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 
Смежные вопросы