【问题标题】:Redefine __init__ of a subclass to take different parameters重新定义子类的 __init__ 以采用不同的参数
【发布时间】:2018-08-12 11:51:39
【问题描述】:
class Date(datetime.date):

    def __init__self(self, year, month, day):
        super().__init__(year, month, day)

假设我创建了这样一个继承自datetime.date 的类,并且我想重新定义__init__ 方法,而不是采用参数yearmonthday,而是采用字符串s,解析它并在 super __init__ 方法中传递解析的变量。像这样的:

class Date(datetime.date):

    def __init__self(self, s):
       args = self.parse(s)
       super().__init__(*args)

这种做法正确吗?我的意思是这在实践中使用了吗?

【问题讨论】:

  • 已经有一个函数可以很容易地做到这一点:dateimte.datetime.strptime,当该功能已经存在时,为什么要对 Date 进行子类化?如果这是您进行子类化的唯一原因,那么子类化毫无意义

标签: python python-3.x class initialization


【解决方案1】:

技术上你可以做到。但是根据Liskov substitution principle,祖先的界面应该类似于其父的界面(但祖先的界面可以更宽)。在您的案例中,将s 作为参数的类不能在传递yearmonthday 的上下文中使用。所以这种方法不是很好。

不过,如果你使祖先的构造函数更复杂,你可以实现这一点:

class Date(datetime.date):
    def __init__self(self, year=None, month=None, day=None, s=None):
       if s is None:
           args = year, month, day
       else:
           args = self.parse(s)
       super().__init__(*args)

但就我而言,我会保持简单并实现如下内容:

class Date(datetime.date):
    def __init__self(self, year, month, day):
        super().__init__(year, month, day)

    @classmethod
    def parse(cls, s):
       args = ...
       return cls(*args)

(正如@Mike Housky 已经提到的,可以省略这样一个微不足道的构造函数;我写它只是为了让我的例子更清楚)

【讨论】:

    【解决方案2】:

    对基类__init__ 方法的调用既正确又必要。如果子类没有,Python 只会调用父类__init__ 方法。

    Python 将允许您省略 super().__init__ 调用,但这会使超类未初始化。这不是真正的继承。或者,也许这不是真正的 OOP,因为您假设继承的方法将在没有调用基类的 __init__ 的情况下工作,这会破坏封装。无论哪种方式,它都不是 OOP。

    将不同的参数传递给超类__init__() 方法也很常见。子类通常需要额外的信息。

    您的示例中的可疑之处在于在对象完全初始化之前对self.parse() 的调用。如果这是您自己的方法,稍后将在Date 类中定义,它可能应该是类方法,而不是实例方法。如果它是从datetime.date 继承的实例方法,则无法保证它会起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-12
      • 2020-04-24
      • 2022-10-13
      • 2021-10-15
      • 2012-07-17
      • 1970-01-01
      • 2023-03-28
      • 2021-12-14
      相关资源
      最近更新 更多