родительский класс Python, 'переносящий' методы дочернего класса

У меня есть следующая ситуация в моем коде Python:

class Parent(object):
    def run(self):
        print "preparing for run"
        self.runImpl()
        print "run done"

class Child(Parent):
    def runImpl(self):
        print "child running"

Однако у меня есть несколько таких 'декораторов', делая различные шаги установки/разрушения прежде и после 'runImpl', и мне не нравится иметь необходимость определить run(), runImpl(), runImplSingleProcess() и т.д.

Я ищу решение следующей формы:

class Parent(object):
    @wrapping_child_call
    def run(self, func_impl, *args, **kwargs)
        print "preparing for run"
        func_impl(*args, **kwargs)
        print "run done"

class Child(Parent):
    def run(self):
        print "child running"

Таким образом нет почти никакой потребности в Дочернем классе для знания об этом продолжении.

Может также быть проблема со множественным наследованием. Если a Child наследовался Parent1 и Parent2, Я честно не знаю то, что должно быть корректным поведением.

Кто-либо знает пользу, естественную, способ выполнить это? или я насилую дизайн здесь?

Спасибо
Yonatan

7
задан Yonatan 14 January 2010 в 15:19
поделиться

2 ответа

Не используйте наследство здесь

Инвертировать ваш дизайн. Вместо реализации родительской дочерней связи, которая представляет собой отношения «IS-A», почему бы не просто иметь состав, поэтому вы получаете отношения «есть»? Вы можете определить классы, которые реализуют методы, которые вы хотели бы, когда ваш предыдущий родительский класс будет создан с помощью этих конкретных классов реализации.

class MyClass:
    def __init__(self, impl)
        self.impl = impl
    def run(self,var):
        print "prepare"
        impl.runImpl(var)
        print "I'm done"

class AnImplementation:
    def runImpl(self,var):
2
ответ дан 7 December 2019 в 14:33
поделиться

Yonatan, ваш вопрос не ясен! В зависимости от ситуации вы можете использовать много разных конструкций.

Одним из растворов будет иметь явную настройку () и методы rundown (), которые вызываются методом Run () перед вызовом runimpl (). Это позволит подклассам обернуть / переопределять их по мере необходимости.

class Runner(object):
    def run(self):
        self.setup()
        self.runImpl()
        self.teardown()
    def setup(self):
        pass
    def teardown(self):
        pass

class RunnerImplementation(Runner):
    def runImpl(self):
        pass # do some stuff
    def setup(self):
        print "doing setup"
        super(RunnerImplementation, self).setup()
    def teardown(self):
        print "doing teardown"
        super(RunnerImplementation, self).teardown()

Однако вы упомянули многократное наследование, что означает, что это не то направление, которое вы должны принимать вообще.

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

Если это так, вы можете определить ресурсы, которые знают, как настроить себя и разрыть себя, и у каждого бегуна будет объявлено, какие ресурсы это требует. Метод RUN () будет выполнять соответствующую настройку / разрывное код каждого ресурса и сделать их доступными для метода RunIMPL ().

class Resource(object):
    name = None # must give a name!
    def setup(self):
        pass
    def teardown(self):
        pass

class DatabaseResource(Resource):
    name = "DB"
    def setup(self):
        self.db = createDatabaseConnection()
    def teardown(self):
        self.db.close()

class TracingResource(Resource):
    name = "tracing"
    def setup(self):
        print "doing setup"
    def teardown(self):
        print "doing teardown"

class Runner(object):
    RESOURCES = []
    def run(self):
        resources = {}
        for resource_class in self.RESOURCES:
            resource = resource_class()
            resource.setup()
            resources[resource_class.name] = resource

        self.runImpl(resources)

        # teardown in opposite order of setup
        for resource in reversed(resources):
            resource.teardown()

class RunnerA(Runner):
    RESOURCES = [TracingResource, DatabaseResource]

    def runImpl(self, resources):
        resources['DB'].execute(...)
1
ответ дан 7 December 2019 в 14:33
поделиться
Другие вопросы по тегам:

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