Как выполнить общие задачи после инициализации в унаследованных классах?

Процесс инициализации группы классов, имеющих общего родителя, можно разделить на три части:

  • Общая инициализация
  • Инициализация для подкласса
  • Общая пост-инициализация

В настоящее время первые две части вызываются из метода __init__ каждого дочернего класса, но финальная часть после инициализации должна вызываться отдельно, например

class BaseClass:
    def __init__(self):
        print 'base __init__'
        self.common1()

    def common1(self):
        print 'common 1'

    def finalizeInitialization(self):
        print 'finalizeInitialization [common2]'


class Subclass1(BaseClass):
    def __init__(self):
        BaseClass.__init__(self)
        self.specific()

    def specific(self):
        print 'specific'


if __name__ == '__main__':
    s = Subclass1()  # Don't forget to finalize the initialization
    s.finalizeInitialization()  # now the object is fully initialized

Есть ли способ не звонить finalizeInitialization()? Или можно перевести вызов на finalizeInitialization() в Subclass1 на __init__ (как в ответ С. Лотта ). Это облегчает жизнь, но все же нужно помнить, чтобы завершить инициализацию, на этот раз внутри «конструктора». В любом случае, нет способа обеспечить полную инициализацию, что я и ищу.

10
задан martineau 8 October 2019 в 20:47
поделиться

5 ответов

Версия 1 - делегировать все.

class Subclass1(BaseClass):
    def __init__(self):
        super( Subclass1, self ).__init__()
        self.specific()
        super( Subclass1, self ).finalizeInitialization()

Версия 2 - делегировать только один шаг

class BaseClass:
    def __init__(self):
        print 'base __init__'
        self.common1()
        self.specific()
        self.finalizeInitialization()

    def common1(self):
        print 'common 1'

    def finalizeInitialization(self):
        print 'finalizeInitialization [common2]'

    def specific( self ):
        # two choices:
        # if this is "abstract": raise an exception
        # if this is "concrete": pass
10
ответ дан 3 December 2019 в 17:22
поделиться

Шаблонный метод проектирования Шаблон для спасения:

class BaseClass:
    def __init__(self, specifics=None):
        print 'base __init__'
        self.common1()
        if specifics is not None:
            specifics()
        self.finalizeInitialization()

    def common1(self):
        print 'common 1'

    def finalizeInitialization(self):
        print 'finalizeInitialization [common2]'


class Subclass1(BaseClass):
    def __init__(self):
        BaseClass.__init__(self, self.specific)

    def specific(self):
        print 'specific'
12
ответ дан 3 December 2019 в 17:22
поделиться

Аналогично подходу С. Лотта, за исключением того, что нет способа ( кроме переопределения __ init __ ) для производных классов, чтобы переопределить (или даже вызвать) общие методы:

class BaseClass:
    def __init__(self):
        def common():
            print "common initialization..."

        def final():
            print "common finalization..."

        common()
        self.specific()
        final()

    def final_init(self):
        print "BaseClass.final_init"


class Subclass1(BaseClass):

    def specific(self):
        print "Subclass1.specific"

Возможно, вы захотите предоставить реализацию по умолчанию , специфичную в BaseClass если не нормально вызывать AttributeError при создании экземпляра любого подкласса, который не обеспечивает свою собственную реализацию.

1
ответ дан 3 December 2019 в 17:22
поделиться

Что не так с вызовом finalInitilazation из init подкласса?

   class BaseClass:
        def __init__(self):
            print 'base __init__'
            self.common1()

        def common1(self):
            print 'common 1'

        def finalizeInitialization(self):
            print 'finalizeInitialization [common2]'


    class Subclass1(BaseClass):
        def __init__(self):
            BaseClass.__init__(self)
            self.specific()
            BaseClass.finalizeInitialization(self)

        def specific(self):
            print 'specific'


    if __name__ == '__main__':
        s = Subclass1() #Don't forget to finalize the initialization
        s.finalizeInitialization()  # now the object is fully initialized
0
ответ дан 3 December 2019 в 17:22
поделиться

Если вам нужно вызывать несколько методов в определенном порядке, это обычно означает, что у проекта есть проблемы с самого начала (это утечка деталей реализации). Поэтому я бы попытался работать с этой целью.

С другой стороны, если люди наследуют класс и должны изменить инициализацию, они должны знать о последствиях - это не то, что вы хотели бы иметь в своем обычном API. , В качестве альтернативы вы можете быть осторожны в отношении окончательной инициализации и проверить, что она вызывается в методах, которые зависят от нее (вызывать ее или вызывать исключение, если нет).

0
ответ дан 3 December 2019 в 17:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: