JVM / Java / SOLID / Liskov Substitution
1. Liskov Substitution Principle (LSP)
Subtypes must be substituable for their base types.
2. Bad Implemenation (violates LSP)
Here, a subtype changes expected behavior.
It throws an exception where the base type contract
says it should process the payment.
package solid.lsp.non_compliant;
public class BadPaymentApplication {
public static void main(String[] args) {
PaymentMethod p1 = new CreditCardPayment();
PaymentMethod p2 = new FreeTrialPayment();
p1.pay(200);
p2.pay(300);
}
}
interface PaymentMethod {
void pay(double amount);
}
class CreditCardPayment implements PaymentMethod {
@Override
public void pay(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Invalid amount");
}
System.out.println("Paid $" + amount + " using Credit Card");
}
}
class FreeTrialPayment implements PaymentMethod {
@Override
public void pay(double amount) {
if (amount > 100) {
throw new UnsupportedOperationException(
"FreeTrial cannot process payments above 100");
}
System.out.println("Free trial payment processed: $" + amount);
}
}
3. LSB-compliant Implementation
Here, payment method defines a contract:
- pay (amount)
- validate (amount must be positive)
All implementation:
- validate the amount
- perform payment
- behave consistently
All payment types behave consistently.
package solid.lsp;
public class PaymentApplication {
public static void main(String[] args) {
PaymentMethod p1 = new CreditCardPayment();
PaymentMethod p2 = new PayPalPayment();
p1.pay(200);
p2.pay(300);
}
}
interface PaymentMethod {
void pay(double amount);
}
abstract class BasePayment implements PaymentMethod {
protected void validate(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Invalid amount");
}
}
}
class CreditCardPayment extends BasePayment {
@Override
public void pay(double amount) {
validate(amount);
System.out.println("Paid $" + amount + " using Credit Card");
}
}
class PayPalPayment extends BasePayment {
@Override
public void pay(double amount) {
validate(amount);
System.out.println("Paid $" + amount + " using PayPal");
}
}