Python中的继承?

3
假设我有以下的 python 基类:

class PythonBase:

class BaseClass(object):
    def a():
        """This method uses method b(), defined in the inheriting class"""

还有一个继承BaseClass的类:

class UsedByUser(BaseClass):
    def b():
        """b() is defined here, yet is used by the base class"""

我的用户只会创建UsedByUser类的实例。典型的用法如下:

if __name__ == '__main__':
    # initialize the class used by the user        
    usedByUser = UsedByUser()

    # invoke method a()
    usedByUser.a()

我的问题是,上述用法是否有问题?这是一种有效的方法,还是必须在BaseClass中定义b()方法,然后在UsedByUser中覆盖它?


2
停止用Java的思维方式...你写的几乎所有内容都不符合Pythonic的风格。 - user780363
弗兰克林所说的话。此外,请阅读Python风格指南 - pillmuncher
4个回答

7

我会在BaseClass中定义b方法:

class BaseClass(object):
    def b(self):
        raise NotImplementedError('b must be implemented by a subclass')

请记住:显式比隐式更好,鉴于方法a无论如何都需要方法b,最好引发一个有意义的异常而不是一个通用的AttributeError

值得指出的是,从语法角度来看,这绝对不是必需的,但它增加了代码的清晰度并强制子类提供一个实现。


感谢您提供如此详细的答案。假设我在BaseClass()中也实现了B()(即提供了一个真正的实现,而不是异常)。那么,在UsedByUser()类中对B()的实现是否总是会覆盖BaseClass()中的定义呢? - user3262424
如果你实例化了UsedByUser类,没错! - GaretJax

0
听起来你想让A调用UsedByUser的受保护成员函数,但这个函数不能放在抽象类BaseClass中。尝试在受保护函数前加下划线(需要注意的是,这只是Python中的一种约定,并没有严格检查,如此处所述)。
class BaseClass(object):
    def A(self):
        print "Grettings from A"
        self._B()
    def _B(self):
        raise NotImplementedError('b must be implemented by a subclass')

class UsedByUser(BaseClass):
    def _B(self):
        """ prefix with underscore is a python convention for a protected member function """
        print "B rocks!"

if ( __name__=='__main__' ):
    usedByUser = UsedByUser()
    usedByUser.A()

关于这个规范的更多信息,请参阅PEP指南

编辑:

正如GaretJax建议的那样, 我添加了一个BaseClass _B方法以增加清晰度。好的提示!


OP没有提到方法b需要任何保护。 - Lutz Prechelt

0
  • 使用是正确的。类可以定义可以被子类覆盖的方法,但这些方法也可以定义新的方法。在超类中定义每个子类所需的方法似乎有点毫无意义。(因为object也需要定义每个函数?)

    一个子类通常具有与另一个子类不同的行为。

    class Vehicle(object): def Refuel(self): # ...

    class Plane(Vehicle): def Fly(self): # ...

    class Car(Vehicle): def Drive(self): # ...

编辑:我误读了代码。
如果只创建它的子类并确保子类有B(),那么理论上是可以的,但风格不好。给超类定义属性和方法,这些属性和方法由超类使用更有意义且更安全。-> 定义B()


但在 OP 的例子中,BaseClass 的方法需要 SubClass 的其中一个方法。在 object 中,没有必要定义每个方法,因为对象不需要它们。 - utdemir
抱歉,你是对的。我没有仔细阅读A()中的注释。 - Niklas R

-1

BaseClass不能假定存在UsedByUser对象,所以它不能使用来自它的B()方法。你可能想在BaseClass中定义一个B(),如果尝试使用不支持它的东西,则什么也不做(如果尝试B()是合理的)或引发异常(如果尝试B()是不合理的)。

如果您告诉我们在您的用例中A和B是什么,我们可能能够更好地为您提供建议。


-1 这样的结构是合法和可能的,而 abc 的存在是为了促进这种用法。 - Marcin
“BaseClass不能假设UsedByUser对象存在”这是正确的。但它并没有做出这种假设(只是更一般性的假设b将存在),那么问题在哪里呢?这只是“模板方法”设计模式。 - Lutz Prechelt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接