하위 클래스에 있는 필드들 중 비슷하게 쓰이는 필드가 있다고 판단되면 (필드명이 다르더라도 기능을 보아야함.) 슈퍼 클래스로 올린다.
필드를 옮기면 해당 필드를 사용하는 동작을 서브 클래스에서 슈퍼클래스로 올릴 수도 있다.
12.1, 12.2는 간단하게 진행이 가능하지만 생성자의 경우 고려해야할 점이 많다.
1. 슈퍼클래스에 생성자가 없다면 정의하고 서브클래스의 생성자들에서 슈퍼클래스의 생성자가 호출되는지 확인한다.
2. 공통 문장을 모두 super() 호출 직후로 변경한다. (문장 슬라이스)
3. 공통 코드를 슈퍼클래스에 추가하고 서브 클래스에서는 제거한다.
생성자 매개변수 중 공통 코드에서 참조하는 값은 모두 super()로 건넨다.
4. 테스트
5. 생성자 시작 부분으로 옮길 수 없는 공통 코드에는 함수 추출하기 + 메서드 올리기를 차례로 적용한다.
하나 또는 소수의 서브 클래스에서 사용되는 메서드의 경우 슈퍼클래스 -> 서브클래스로 이동
하나 또는 소수의 서브 클래스에서 사용되는 필드의 경우 슈퍼클래스 -> 서브클래스로 이동
// bad case
function createEmployee(name, type) {
return new Employee(name, type);
}
// good case
function createEmployee(name, type) {
switch(type) {
case "engineer": return new Engineer(name);
case "salesperson": return new Salesperson(name);
case "manager": return new Manager(name);
}
}
비슷한 대상을 특정 특성에 따라 구분하는 경우 타입 코드를 사용하여 분리하게 되는데 이 때 서브클래스를 사용하여 리팩토링 하자.
// bad case
class Person {
get genderCode() { return "X";}
}
class Male extends Person {
get genderCode() { return "M";}
}
class FeMale extends Person {
get genderCode() { return "F";}
}
// good case
class Person {
get genderCode() { return this._genderCode;}
}
서브클래스가 활용되지 않거나 필요하지 않은 방식으로 만들어지는 경우 제거하고 슈퍼클래스의 필드로 대체하자.
비슷한 일을 수행하는 두 클래스가 보이면 상속 메커니즘을 이용해 비슷한 부분을 공통의 슈퍼클래스로 옮겨 담을 수 있다.
공통된 부분
데이터: 필드 올리기
동작: 메서드 올리기
// bad case
class Department {
get totalAnnualCost() {}
get name() {}
get headCount() {}
}
class Employee {
get annualCost() {}
get name() {}
get id() {}
}
// good case
class Party {
get name() {}
get annualCost() {}
}
class Department extends Party {
get annualCost() {}
get headCount() {}
}
class Employee extends Party {
get annualCost() {}
get id() {}
}
어떤 클래스와 부모가 너무 비슷해져서 독립적으로 존재해야 할 이유가 사라질 때 하나로 합쳐야한다.
// bad case
class Employee {}
class Salesperson extends Employee {}
// good case
class Employee {}
상속의 단점
1. 한 번만 사용할 수 있다.
무언가가 달라져야 하는 이유가 여러 개여도 상속에서는 그중 단 하나의 이유만 선택해 기준으로 삼아야한다.
2. 상속은 클래스들의 관게를 아주 긴밀하게 결합한다.
이 문제를 위임으로 해결할 수 있다.
예시코드 참조
상속이 혼란과 복잡도를 키우는 방식으로 이뤄지기도 한다. (이런 경우 위임이 필요함.) 슈퍼클래스의 기능들이 서브클래스에는 어울리지 않는다면 그 기능들을 상속을 통해 이용하면 안된다.
ex) 자바의 스택 클래스
상속을 먼저 적용하고 나중에 문제가 생기면 슈퍼클래스를 위임으로 바꾸자.