Liskov Substitution Principle
An operation on a base class must operate on a derrived class without explict knowledge of the type.
package lsp; /** * use polymorphism and delegation to obey LSP */ public class Lsp { public static void main(String[] args) { new Lsp() ; } public Lsp() { Cat pet1 = new Cat() ; Dog pet2 = new Dog() ; Pet pets[] = { pet1, pet2 } ; // avoid using instanceof or getClass().getName() for( int i=0 ; i<pets.length ; i++ ) { if (pets[i] instanceof Cat) { System.out.println( pets[i].getClass().getName()+" goes "+ ((Cat) pets[i]).meow() ) ; } else if (pets[i] instanceof Dog) { System.out.println( pets[i].getClass().getName()+" goes " + ((Dog) pets[i]).woof() ) ; } } // uses polymorphism but // still ties this code to implemention of Pet for( int i=0 ; i<pets.length ; i++ ) { System.out.println( pets[i].getClass().getName()+" goes "+pets[i].getIdeophone() ) ; } // Use delegation to acheive LSP // make code flexible and resusable. for( int i=0 ; i<pets.length ; i++ ) { pets[i].ideophone( System.out ) ; } } public abstract class Pet { // brittle interface public abstract String getIdeophone() ; // robust interface public abstract void ideophone( java.io.PrintStream printStream ) ; } public final class Dog extends Pet { // brittle interface public String getIdeophone() { return woof() ; } private String woof() { return "woof" ; } // robust interface public void ideophone( java.io.PrintStream printStream ) { woof( printStream ) ; } private void woof(java.io.PrintStream printStream) { printStream.println( this.getClass().getName()+" goes woof" ) ; } } public final class Cat extends Pet { // brittle interface public String getIdeophone() { return meow() ; } private String meow() { return "meow" ; } // robust interface public void ideophone( java.io.PrintStream printStream ) { meow( printStream ) ; } private void meow(java.io.PrintStream printStream) { printStream.println( this.getClass().getName()+" goes meow" ) ; } } }