Python 扩展父类的 extend 方法

22 阅读2分钟

在编码一个 Google Appengine 应用时,有时我们需要在子类中使用定义在父类中的方法。不过在实现中,这些方法可能会被重复定义,这会造成代码冗余。例如,在下面的代码中,我们定义了一个父类 Object 和两个子类 ObjectBoolean 和 ObjectInteger,它们都定义了两个方法 message_to_model 和 model_to_message。为了避免代码重复,我们希望能在子类中重用父类中的方法。

from google.appengine.ext.ndb import polymodel
from google.appengine.ext import ndb
from endpoint_messages.object import *

class Object(polymodel.PolyModel):
    name = ndb.StringProperty(required=True, verbose_name="Name")
    description = ndb.TextProperty(verbose_name="Description")
    created = ndb.DateTimeProperty(auto_now_add=True, verbose_name="Created")
    modified = ndb.DateTimeProperty(auto_now=True, verbose_name="Modified")

    def model_to_message(self):
        return ObjectResponseMessage(class_name=self._class_name(),
                                     id=self.key.integer_id(),
                                     name=self.name,
                                     description=self.description,
                                     created=self.created,
                                     modified=self.modified)

    def message_to_model(self, request):
        self.name = request.name
        self.description = request.description
        self.created = request.created
        self.modified = request.modified

class ObjectBoolean(Object):
    current = ndb.BooleanProperty(verbose_name="Current")
    target = ndb.BooleanProperty(verbose_name="Target")

    def model_to_message(self):
        return ObjectResponseMessage(class_name=self._class_name(),
                                     id=self.key.integer_id(),
                                     name=self.name,
                                     description=self.description,
                                     created=self.created,
                                     modified=self.modified,
                                     boolean=ObjectBooleanMessage(current=self.current,
                                                                  target=self.target))

    def message_to_model(self, request):
        self.name = request.name
        self.description = request.description
        self.created = request.created
        self.modified = request.modified
        if request.boolean:
            self.current = request.boolean.success
            self.target = request.boolean.target

class ObjectInteger(Object):
    current = ndb.IntegerProperty(verbose_name="Current")
    target = ndb.IntegerProperty(verbose_name="Target")

    def model_to_message(self):
        return ObjectResponseMessage(class_name=self._class_name(),
                                     id=self.key.integer_id(),
                                     name=self.name,
                                     description=self.description,
                                     created=self.created,
                                     modified=self.modified,
                                     float=ObjectIntegerMessage(current=self.current,
                                                                target=self.target))

    def message_to_model(self, request):
        self.name = request.name
        self.description = request.description
        self.created = request.created
        self.modified = request.modified
        if request.integer:
            self.current = request.integer.current
            self.target = request.integer.target

2、解决方案

我们可以使用 Python 中的 super() 函数来解决这个问题。super() 函数可以让我们在子类中调用父类的方法,而不需要重新定义这些方法。

在下面的代码中,我们在 ObjectBoolean 子类中使用 super() 函数来调用父类 Object 中的 message_to_model 方法。这样,我们就避免了代码冗余。

class ObjectBoolean(Object):
    current = ndb.BooleanProperty(verbose_name="Current")
    target = ndb.BooleanProperty(verbose_name="Target")

    def model_to_message(self):
        super(ObjectBoolean, self).message_to_model(request)

        if request.boolean:
            self.current = request.boolean.success
            self.target = request.boolean.target

    def message_to_model(self, request):
        super(ObjectBoolean, self).message_to_model(request)

        if request.boolean:
            self.current = request.boolean.success
            self.target = request.boolean.target

同样地,我们也可以在 ObjectInteger 子类中使用 super() 函数来调用父类 Object 中的方法。

class ObjectInteger(Object):
    current = ndb.IntegerProperty(verbose_name="Current")
    target = ndb.IntegerProperty(verbose_name="Target")

    def model_to_message(self):
        super(ObjectInteger, self).message_to_model(request)

        if request.integer:
            self.current = request.integer.current
            self.target = request.integer.target

    def message_to_model(self, request):
        super(ObjectInteger, self).message_to_model(request)

        if request.integer:
            self.current = request.integer.current
            self.target = request.integer.target

现在,我们就可以在子类中重用父类中的方法,而不需要重复定义这些方法。这使得我们的代码更加简洁和易于维护。