SOLID에서 L에 해당되는 Liskov Substitution Principle(LSP)이다. 이 원칙은 서브 타입은 기반 타입을 대체할 수 있다는 법칙이다. 즉, 부모 클래스 A를 상속한 클래스 B는 언제든 A클래스를 대체할 수 있다는 뜻이다. 이것은 다형성(polymorphism)을 말한 법칙이다. 이것을 코드로 확인해보고자 한다.
const Rectagle = class {
constructor(width, height) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
};
const Square = class extends Rectagle {
constructor(length) {
super(length, length);
}
getArea() {
return this.width * this.height + "입니다.";
}
};
const rec = new Square();
rec.width = 10;
rec.height = 20;
console.log("rec", rec.getArea()); // rec 200입니다.
const rec2 = new Rectagle(5, 7);
rec2.width = 10;
rec2.height = 20;
console.log("rec2", rec2.getArea()); // rec2 200
위 코드는 LSP를 위반했다. Square클래스의 getArea()메소드는 number 타입을 반환해야하는데 string을 반환하고 있다. 이는 부모와의 규약을 어긴행동이고 서브타입인 Square가 기반타입인 Rectangle을 대체할 수 없기 때문이다. 위 코드를 LSP를 위배하지 않고 하려면 같은 number타입을 반환해야 한다.
const Animal = class {
constructor(name) {
this.name = name;
}
say() {
console.log("my name is", this.name);
}
};
const Person = class extends Animal {
constructor(name) {
super(name);
}
say(age) {
console.log("my name is", this.name, age);
}
};
const App = class {
constructor(person) {
this.person = person;
}
run() {
this.person.say();
}
};
const app = new App(new Person("철현"));
app.run();
Person클래스의 say 메소드는 Animal클래스의 say 메소드는 필요한 인자가 다르다(시그니처가 다르다) 그래서 Animal클래스를 상속받은 Person클래스는 Animal클래스를 대체할 수 없다.
const Animal = class {
constructor() {}
speak() {
throw "override method!";
}
};
const Cat = class extends Animal {
constructor() {
super();
}
speak() {
console.log("냥냥!");
}
};
const Dog = class extends Animal {
constructor() {
super();
}
speak() {
console.log("왈왈!");
}
};
const Fish = class extends Animal {
constructor() {
super();
}
speak() {
throw "난 짖을 수 없어요.";
}
};
const animalArr = [new Cat(), new Dog(), new Fish()]; // Animal이니까 가능
for (const animal of animalArr) {
animal.speak(); // error (fish는 speak이 에러)
}
다음과 같이 Animal의 speak()메소드를 override하도록 Animal클래스의 speak을 추상 메소드로 만들어 놓았다. 하지만 speak()이 불가능한 Fish클래스가 Animal클래스를 오버라이딩 했기 때문에 하단에서 에러가 났다.
이와 같은 문제는 정상적으로 실행하다가 런타임에 발견되어 협업하는 개발자에게 큰 문제를 일으킨다.
다형성을 원칙화한 LSP를 잘 활용한다면 유연한 코드를 제공하지만 잘못된 사용은 협업관계에 문제를 일으키기 때문에 조심해야 한다.
자바스크립트에서는 형이 자유롭기 때문에 크게 사용될 일이 없을 것 같지만, 프로그래밍 개발론 중 보편화된 개체지향을 이해하기 위해 정리해 보았다.
참조