Puoi rispondere a domande come questa tornando ai primi principi e chiedendo "qual è il principio di sostituzione di Liskov che intende raggiungere?" E la risposta è che il codice che funziona correttamente con la superclasse dovrebbe funzionare correttamente anche con tutte le sottoclassi. (Ai fini della teoria di CS esiste una definizione matematica più specifica, ma per il programmatore di lavoro comune che potrebbe essere preoccupante solo se si sta creando un linguaggio di programmazione).
Quindi, perché una classe astratta dovrebbe essere più facile? Non c'è davvero alcuna situazione in cui l'uso di una classe concreta significhi che non è possibile seguire il principio di sostituzione di Liskov nelle sottoclassi. Dopo tutto, la superclasse definisce un contratto per le sottoclassi in entrambi i casi. Il fatto che contenga anche una possibile implementazione del contratto non è né qui né là.
Tuttavia, si potrebbe argomentare che psicologicamente è più facile concentrarsi su un contratto quando si crea una classe astratta, e forse una classe concreta potrebbe prendere un dettaglio di implementazione e accidentalmente rendere quella parte del contratto. Sembra un po 'plausibile senza essere davvero convincente.
Per non usare mai una classe concreta - forse una buona regola empirica è di essere un po 'scettici su qualsiasi filosofia di progettazione che dice che dovresti mai usare una caratteristica standard, non totalmente rotta di un linguaggio. In questo caso, la possibilità che tu possa, forse, essere più propensa a commettere un errore nel progettare il contratto di una classe concreta rispetto a una astratta - beh questo sarebbe nel migliore dei casi un fattore minore nel prendere tale decisione.