Este puede o no ser una violación del LSP.
En serio. Escúchame.
Si sigue el LSP, los objetos del tipo ProjectTask
deben comportarse como se espera que se comporten los objetos del tipo Task
.
El problema con su código es que no ha documentado cómo se espera que se comporten los objetos de tipo Task
. Has escrito código, pero no hay contratos. Agregaré un contrato para Task.Close
. Dependiendo del contrato que agregué, el código para ProjectTask.Close
cumple o no sigue el LSP.
Dado el siguiente contrato para Task.Close, el código para ProjectTask.Close
no sigue el LSP:
// Behaviour: Moves the task to the closed state
// and does not throw any Exception.
// Default behaviour: Moves the task to the closed state
// and does not throw any Exception.
public virtual void Close()
{
Status = Status.Closed;
}
Dado el siguiente contrato para Task.Close, el código para ProjectTask.Close
sigue el LSP:
// Behaviour: Moves the task to the closed status if possible.
// If this is not possible, this method throws an Exception
// and leaves the status unchanged.
// Default behaviour: Moves the task to the closed state
// and does not throw any Exception.
public virtual void Close()
{
Status = Status.Closed;
}
Los métodos que pueden anularse deben documentarse de dos maneras:
-
El "Comportamiento" documenta en qué puede confiar el cliente que sabe que el objeto del destinatario es un Task
, pero no sabe de qué clase es una instancia directa. También les dice a los diseñadores de las subclases cuáles sustituciones son razonables y cuáles no son razonables.
-
El "comportamiento predeterminado" documenta en qué puede confiar un cliente que sabe que el objeto del destinatario es una instancia directa de Task
(es decir, qué obtiene si usa new Task()
. También le dice a los diseñadores de las subclases, qué comportamiento se heredará si no anulan el método.
Ahora deben mantenerse las siguientes relaciones:
- Si S es un subtipo de T, el comportamiento documentado de S debería refinar el comportamiento documentado de T.
- Si S es un subtipo de (o igual a) T, el comportamiento del código de S debe refinar el comportamiento documentado de T.
- Si S es un subtipo de (o igual a) T, el comportamiento predeterminado de S debería refinar el comportamiento documentado de T.
- El comportamiento real del código para una clase debe refinar su comportamiento predeterminado documentado.