重新定义子类的__init__以采用不同的参数

时间:2018-08-12 11:51:40

标签: python python-3.x class initialization

class Date(datetime.date):

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

假设我创建了一个继承自datetime.date的类,并且我想重新定义__init__方法,因此不要采用参数yearmonth和{{1} },以获取字符串day,对其进行解析,并以超级s方法传递解析后的变量。像这样:

__init__

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

2 个答案:

答案 0 :(得分: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已经提到的那样,可以忽略这样一个琐碎的构造函数;我只是为了使我的例子更清楚而写了它)

答案 1 :(得分:0)

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

Python将让您忽略该super().__init__调用,但这将使超类未初始化。那不是真正的继承。或者,也许不是真正的OOP,因为您假设继承的方法在不调用基类的__init__的情况下就可以工作,并且破坏了封装。无论哪种方式,都不是OOP。

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

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