-
Liskov Substitution Principlepython/SOLID 2023. 12. 6. 22:53
정의
Subclasses should NOT change the behavior of superclasses in unexpected ways.
Selecting on types 유형
위반 코드
class Employee: def __init__(self, name): self.name = name class Manager(Employee): def __init__(self, name, department): super().__init__(name) self.department = department def print_employee(e): if type(e) is Employee: print(f"{e.name} is an employee") elif type(e) is Manager: print(f"{e.name} leads department {e.department}")
- Manager 클래스의 인스턴스가 필요한 곳에, Employee 클래스(Manager 클래스의 superclass) 의 인스턴로 대체할 수 없다. (Manager type 인지 Employee type 인지 체크되어야 대체될 수 있다.)
개선 코드
https://wefree.tistory.com/328 참고
Break the is-a relationship 유형
위반 코드
아래처럼 초기 Employee 코드에서
class Employee: def __init__(self, name, salary): self.name = name self.salary = salary def print_year_salary(self): print(f"{self.name} year salary ${self.salary * 12}")
salary 를 받지 않는 Intern 클래스를 Employee 클래스를 상속 받아 추가했다.
class Intern(Employee): def __init__(self, name, salary): # Intern 은 salary 를 받지 않으므로 None 으로 세팅, 0 으로 세팅하는 것이 좋을거라 생각할 수 있지만? super().__init__(name, None)
- salary 값을 None 으로 세팅했는데, 0 이 더 좋을거라 생각할 수도 있다. 0으로 세팅했을 경우, 만약 Employee 의 평균 salary 값을 구하는 함수를 추가할 때 0 으로 세팅한 값 때문에 문제가 될 수 있다. (None 과 0 은 다르다!)
Intern 의 salary 값이 None 이기 때문에, superclass 의 print_year_salary() 가 잘 동작하기 위해서는 아래처럼 수정되어야 한다.
def print_year_salary(self): if type(self) is not Intern: print(f"{self.name} year salary ${self.salary * 12}")
즉, subclass Intern 때문에 superclass Employee 의 print_year_salary() 가 변경되어야 했다 !!!
근본적으로 Intern 을 Employee 로 부터 상속받아 is-a 관계를 만든것이 잘못이다.
Raise error in overridden method 유형
위반 코드
class Employee: def __init__(self, name): self.name = name def promote(self): print("Promote employee") class Intern(Employee): def promote(self): raise NotImplementedError("Interns cannot be promoted") def promote_employee(e): e.promote()
- pormote() 함수의 경우 superclass 인 Employee 에서는 Exception 이 발생하지 않는데, subclass 인 Intern 의 경우 Exception 이 발생할 수 있다.
- Employee 인스턴스를 받아 Exception 발생 없이 잘 처리되던 promote_employee() 함수였다. 그런데 Employee 인스턴스 대신에 subclass 인 Intern 인스턴스로 교체했더니 promete_employee() 호출 도중 Exception 이 발생해 프로그램이 깨져버렸다.
Break constraints
위반 코드
아래처럼 초기 코드가 있는 상태에서
class Employee: def __init__(self, employee_id, name): self.employee_id = employee_id self.name = name def is_employee_id_valid(self): return type(self.employee_id) is int and self.employee_id > 0 class Intern(Employee): def __init__(self, employee_id, name): super().__init__(employee_id, name)
Intern 클래스의 employee_id 는 I 로 시작하도록 변경해 달라고 요청이 왔다. 시간이 없어 꼼수로 아래처럼 수정했다.
class Intern(Employee): def __init__(self, employee_id, name): super().__init__(f"I{employee_id}", name)
그런데, 이렇게 구현할 경우 superclass 의 is_employee_id_valid() 의도에서 벗어나게된다. (superclass 를 수정해야 하나?)
참고: https://www.udemy.com/course/solid-design-principles-with-python
'python > SOLID' 카테고리의 다른 글
Dependency Inversion Principle (0) 2023.12.06 Interface Segregation Principle (0) 2023.12.06 Open-closed Principle (1) 2023.12.06 Single Responsibility Principle (0) 2023.12.05