9

私の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()ParentChildChildSingleProcess

次の形式のソリューションを探しています。

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"

このように、Child クラスはこれを意識する必要はほとんどありません。

多重継承の問題もあるかもしれません。aがandChildから継承する場合、正直なところ、正しい動作がどうあるべきかわかりません。Parent1Parent2

これを達成するための良い、自然な方法を知っている人はいますか? それとも私はここでデザインをレイプしていますか?

ありがとう
ヨナタン

4

3 に答える 3

3

ここでは継承を使用しないでください

デザインを反転します。「is-a」関係である親子実装の代わりに、「has-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):
于 2010-01-14T15:26:50.967 に答える
1

Yonatan、あなたの質問は明確ではありません !状況に応じて、さまざまなデザインを使用できます。

1 つの解決策は、runImpl() を呼び出す前に、run() メソッドによって呼び出される明示的な setup() および teardown() メソッドを用意することです。これにより、サブクラスは必要に応じてこれらをラップ/オーバーライドできます。

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(...)
于 2010-01-14T16:11:41.633 に答える