Python 如果字段>;查菲尔德>;EmailField,EmailField是否用CharField打破了Liskov替换原理?

Python 如果字段>;查菲尔德>;EmailField,EmailField是否用CharField打破了Liskov替换原理?,python,oop,theory,liskov-substitution-principle,Python,Oop,Theory,Liskov Substitution Principle,假设我正在用表单类编写一个webapp,而表单类可以有几个字段 字段本身是一个抽象类。它包含一个抽象的validators属性,该属性是它将调用以确定字段内容是否有效的方法列表。这些验证器由实例方法字段调用调用。运行验证器(值) CharField是允许任意文本的Field子类。此字段始终有效,只要为其指定了长度非零的字符串 EmailField是一个具有附加要求的CharField子类。只有当value通过一组某种测试时,此字段才有效。(例如,值中的“@”) 我的问题是:EmailField是

假设我正在用
表单
类编写一个webapp,而
表单
类可以有几个
字段

字段
本身是一个抽象类。它包含一个抽象的
validators
属性,该属性是它将调用以确定字段内容是否有效的方法列表。这些验证器由实例方法
字段调用调用。运行验证器(值)

CharField
是允许任意文本的
Field
子类。此字段始终有效,只要为其指定了长度非零的字符串

EmailField
是一个具有附加要求的
CharField
子类。只有当
value
通过一组某种测试时,此字段才有效。(例如,值中的“@”)

我的问题是:
EmailField
是否打破了与
CharField
相关的LSP?它应该是兄弟类吗?尽管
Field
通过允许子类提供自己的
验证器来定义可变性,
TextField
并没有明确扩展这种可变性

我一直试图找到更多关于LSP的解释,但它们都重用了相同的矩形/正方形示例

鉴于:

def传输(字段):
“”“字段必须是TextField实例。”“”
断言isinstance(字段,文本字段)
实例。运行_验证器(“hello”)
使用
CharField
时,
transmograte(my_text_field)
将毫无问题地运行。但是如果
my\u text\u字段
EmailField
的一个实例,它将始终引发一个
ValidationError
。这是否违反了LSP?还是我的推理完全颠倒了?(这种情况经常发生)


您还可以愉快地想象
运行_validators()
返回
False
,而不是在某种程度上改变分析时引发异常;我只是想让我的示例尽可能接近源材料。

我认为只要EmailField提供与CharField相同的方法(看起来是这样的),设计就可以了。如果它仍然像鸭子一样嘎嘎叫,它就会跟随LSP。子类具有不同的实现或行为是可以的。

但是对于打破LSP的常见矩形/正方形示例也是如此。Square提供了相同的方法,所以它仍然像鸭子一样嘎嘎作响。但它的行为出人意料,我认为这是导致它打破LSP的原因。好的一点。。。我很想听到关于这个问题的其他答案。我认为它与矩形/正方形有点不同,因为据我所知,正方形的问题是setHeight和setWidth现在会做一些意想不到的事情。然而,在本例中,run_validators()仍然只是告诉我们它是否有效,尽管逻辑略有不同。由于它是在用户数据上运行的,我认为这种行为上的差异不会影响现实世界中的程序员。只要它工作,谁会在乎呢?