Python: 子类可以重载继承的方法吗?

8 投票
2 回答
16144 浏览
提问于 2025-04-15 20:08

我正在Google App Engine上制作一个购物车应用。我的代码中有很多类都是从一个基础处理器(handler)派生出来的:

class BaseHandler(webapp.RequestHandler):
    def get(self, CSIN=None):
        self.body(CSIN)

这是否意味着每个子类的body()方法都需要有相同的参数?这太麻烦了。其实只有一个子类真正使用了这个参数。那如果我以后添加新的参数呢?我是不是得逐个去修改每个类?

class Detail(BaseHandler):
    def body(self, CSIN):

class MainPage(BaseHandler):
    def body(self, CSIN=None): #@UnusedVariable

class Cart(BaseHandler):
    def body(self, CSIN): #@UnusedVariable

2 个回答

5

在Python中,方法的重载只根据名字来匹配。这意味着

class Base:
  def method(self, param2):
     print "cheeses"

class NotBase(Base):
  def method(self):
     print "dill"

obj = NotBase();
obj.method() 

会输出dill(,而当你用obj.method("stuff")时就会出错。

不过,在你的情况下,这种行为并不是你想要的。如果你在子类中重载了body方法,但参数比基类的get方法需要的少,那么当你在这些类上调用get方法时就会出错。

8

重写的方法原则上不需要有相同的参数,但它们在调用时必须有相同的形式参数。也就是说,由于任何处理器都可以通过 get 调用 body,所以它们的参数必须一致。实际上,重写的目的就是让调用者不知道对象的确切类,因此如果它们的参数不相同,通常调用者就不知道该传什么参数。所以,使用不同参数的重写方法可能会有点奇怪。

如果你改变了调用时的参数,那么你确实需要修改函数以匹配。这和继承没有关系,而是关于Python函数是如何工作的。

如果你想要更多的灵活性,可以使用关键字参数,这是一种将字典作为参数传递的高级方式:

class Detail(BaseHandler):
    def body(self, **kwargs):
        print kwargs['CSIN']

class MainPage(BaseHandler):
    def body(self, **kwargs): # can ignore kwargs

class Cart(BaseHandler):
    def body(self, **kwargs): # can ignore kwargs

class BaseHandler(webapp.RequestHandler):
    def get(self, CSIN=None):
        self.body(CSIN = CSIN, some_new_arg = 3)

class SomeNewHandler(BaseHandler):
    def body(self, **kwargs):
        print kwargs['some_new_arg']

不过,我对这样做的智慧有点怀疑:如果你经常添加新参数,而大多数实现又忽略了大部分参数,那么也许 body 并不真的是这些参数的函数。实际上,这些参数可能是处理器对象的状态,只是恰好作为参数传递而已。显然,这种区别有点主观——对于每个对象只调用一次的函数,传递一个字典和使用 self 作为字典之间并没有太大的实际区别。

撰写回答