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를 잘 활용한다면 유연한 코드를 제공하지만 잘못된 사용은 협업관계에 문제를 일으키기 때문에 조심해야 한다.
자바스크립트에서는 형이 자유롭기 때문에 크게 사용될 일이 없을 것 같지만, 프로그래밍 개발론 중 보편화된 개체지향을 이해하기 위해 정리해 보았다.
참조