Single Responsibility
Class should only have one clear reason to change (one responsibility).
Open/Closed Principles
Class should be open to extension (inheritance), but closed for modification.
Liskov Substitution
Ensures subclass can substitute its superclass.
Parameter type of overrides should match or more abstract of
foo(Parent) to
✅foo(GrandParent)
❌foo(Child)
Break if client passes Parent to foo, but foo is actually expecting Child, tried to access fields not available on Parent
Return type of overrides should match or subtype of
Parent foo() to
✅Child foo()
❌GrandParent foo()
Breaks when client tries to access fields on Parent, but not available on GrandParent
Overriden shouldn’t throw more than it’s base
Breaks when additional exceptions were not expected by client, and were raised
Subclass shouldn’t strengthen pre conditions (increasing requirements established by superclass)
Breaks when client believes the object it’s passing satisfies the conditions set by superclass of another object, but the object is actually a subclass of the superclass that needs extra conditions
Subclass shouldn’t weaken post conditions (failing to uphold guarantees established by superclass)
Breaks when client expects objects that passes certain conditions, but subclass actually doesn’t satisfy it
Subclass should preserve Invariants of superclass
Breaks when superclass expects studentCount to be non negative, but subclass makes it negative
Subclass shouldn’t modify private fields of superclass
Allowing subclasses to access private fields can lead to tight coupling between the superclass and its subclasses
The superclass may enforce certain invariants through its public methods. Direct access to private fields by the subclass can bypass these checks
Interface Segregation
Break down “fat” interfaces into more specific ones. not all classes are able to satisfy a bloated interface.
Class shouldn’t be forced to conform to its interfaces.
Dependency Inversion Principle
High level should depend on abstractions. Low level should depend on abstractions
On early app development, low level classes are often developed first before high level classes. dependency inversion principle suggests changing the direction of the dependency

