Ако Field › CharField › EmailField, EmailField нарушава ли принципа на заместване на Liskov с CharField?

Да кажем, че пиша webapp с Form клас, а Form клас може да има няколко Fields.

Самият Field е абстрактен клас. То съдържа абстрактно свойство validators, което е списък от методи, които ще извика, за да определи дали съдържанието на полето е валидно или не. Тези валидатори се извикват чрез извикване на метода на екземпляра Field.run_validators(value)

CharField е Field подклас, който позволява произволен текст. Това поле е винаги валидно, стига да му бъде даден низ с ненулева дължина.

EmailField е подклас CharField с допълнителни изисквания. Това поле е валидно само когато value премине набор от тестове от някакъв вид. (напр. '@' in value).

Моят въпрос тук е: EmailField нарушава ли LSP по отношение на CharField? Трябва ли вместо това да е клас за брат или сестра? Въпреки че Field дефинира променливостта, като позволява на подкласовете да предоставят свои собствени validators, TextField не разширява изрично тази променливост.

Продължавам да се опитвам да намеря повече обяснения на LSP, но всички те използват повторно един и същ пример за правоъгълник/квадрат.

дадени:

def transmogulate(field):
    """field must be a TextField instance."""
    assert isinstance(field, TextField)
    instance.run_validators("hello")

Когато използвате CharField, transmogulate(my_text_field) ще работи без проблем. Но ако вместо това my_text_field е екземпляр на EmailField, той винаги ще повдига ValidationError. Това нарушение на ЗУД ли е? Или разсъжденията ми са напълно назад? (което се случва достатъчно често)

Също така можете също толкова щастливо да си представите run_validators() да връща False вместо да предизвика изключение, ако това промени анализа по някакъв начин; Просто исках да запазя примера си възможно най-близо до изходния материал.


person Dan Passaro    schedule 11.06.2013    source източник
comment
Докато работи, на кого му пука?   -  person clavio    schedule 11.06.2013


Отговори (1)


Мисля, че дизайнът е добре, стига EmailField да предоставя същите методи като CharField (което изглежда така). Следва LSP, ако все още кряка като патица. Добре е подкласовете да имат различни реализации или поведение.

person bwbrowning    schedule 11.06.2013
comment
Но същото важи и за обичайния пример за правоъгълник/квадрат, който нарушава LSP. Square предоставя същите методи, така че все още кряка като патица. Но се държи неочаквано, което според мен е причината да наруши LSP. - person Dan Passaro; 11.06.2013
comment
Добра точка... Интересно ми е да чуя други отговори по този въпрос. Мисля, че е малко по-различен от правоъгълник/квадрат, защото проблемът с квадрата, както разбирам, е, че setHeight и setWidth сега правят неочаквани неща. Въпреки това, в този случай run_validators() все още просто ни казва дали е валиден или не, макар и с малко по-различна логика. И тъй като работи с потребителски данни, не мисля, че тази разлика в поведението засяга програмиста в реалния свят. - person bwbrowning; 11.06.2013