서브클래스, 서브타입, 클래스들간의 각종 관계 등에 대해 정리해보고자 시리즈물로 준비했다.
나는 이 부분에 대해 전혀 모르기 때문에 간단한 정리가 될 것이다.
2. Aggregation 과 Composition 개념
3. Subtype 과 Subclass
봐도 봐도 헷갈린다. 그래도 이제는 헷갈릴 때 마다 여러번 봐 놓았었더니 wiki 내용이 조금 와 닿기 시작했다.
wiki 에 있는 Is-a 와 관련된 설명들을 바탕으로 s-a , has-a 등 각종 타입간의 관계와 이를 리스코프 치환 원칙과 연관 지어 정리 해 보기로 했다.
타입 및 클래스들 사이에 존재하는 각 종 관계들과 리스코프 치환 원칙
리스코프 치환원칙 과 “Java 에서의 is-a 관계” 라는 말로 특정지어서 깔끔하게 정리하고 끝내 야겠다.
- 타입 및 클래스들 사이에 존재하는 has-a 관계와 is-a 관계 그리고 instance-of 관계
- super타입/클래스 - sub타입/클래스 관계
- sub타입/클래스는 super타입/클래스 에 대하여 “type-of(is-a)” 관계를 갖는다.
- 전체(whole)/엔티티/컨테이너 - 부분(part)/구성요소/멤버 관계
- aggregation (소유 관계 없음) 관계 : “전체” 는 “부분” 과 “has-a” 관계를 갖는다.
- composition ( 소유 관계가 존재 ) 관계 : “constituent(구성요소)” 는 “entity” 와 “part-of” 관계를 갖는다.
- containment 관계 : “member” 는 “container” 에 대해 “member-of” 관계를 갖는다.
- concept-object(type-token) 관계 : classes(types) 와 instances(objects) 사이의 관계
- object 는 클래스(타입) 에 대해 instance-of 관계를 갖는다
- super타입/클래스 - sub타입/클래스 관계
다양한 관계들에 대한 정의들이다.
나는 여기서 "서브타입" 과 "서브클래스" 가 같은 의미인가? 하는 의문이 생겼다. 이에 대해서는 다음 포스트에서 다룰 예정이다. 굉장히 학문적인 내용이었다..
또한 여기서 aggregation 과 composition 이라는 것이 등장한다. 둘다 뭔가 집합-부분 사이의 관계를 의미하는 듯 하다.
하지만 "소유관계가 있고 없고" 에서의 차이가 보이는데 이것만 보고는 잘 와닿지 않는다.
에서는 이에 대해 간략하게 정리하며 예시를 들었다.
리스코프 치환원칙
다음으로는 리스코프 치환원칙에 대해 살펴보자.
- 리스코프 치환원칙 : Base 클래스(B) 와 Child 클래스(C) 사이 에 상속 관계가 존재할 경우, B 타입의 어떠한 객체던 간에 C 타입의 객체로 대체 될 수 있다.
- 중요한 것은 C 타입 객체로 대체 되었을 때 이상 없어야 한다는 것.
- B 에 대해 기대되는 것이 C 를 통해서도 이뤄져야 한다.
- LSP 은 내가 체크해 봐야할 세부적인 규칙을 주는 것 으로 볼 수 있다.
- 따라서 오버라이딩 에서 리턴 타입, 인자 타입 등을 맘대로 변경할 수 없고, 접근 제한 정도를 더 좁게 만들 수도 없다. 그리고 개발자 스스로는 로직이 상위클래스에서 제공되는 것과 완전히 별개의 로직을 작성 하지는 않도록 해야 할 것이다.
나의 결론
“is-a 관계와 리스코프치환원칙이 어떤 차이가 있지? “ 라는 혼란으로부터 각종 관계에 대한 개념을 정리해 보았는데 내 결론은 다음과 같다.
- is-a 관계 더라도 리스코프 치환원칙을 만족 하느냐 는 개발자가 코드를 어떻게 작성해 놓았느냐 에 따라 달라질 것이다.
- 언어차원에서 is-a 관계를 가진 클래스들 사이에 "subtyping 과 관련된 강제적인 규칙" 을 지원하지 않는한 , 개발자의 코드에 달려 있는 것 같다.
- Java 에서 extends 를 통한 상속을 했다면 이는 is-a 관계를 정의한 것이다. 하지만 서브 클래스에서 로직 구현을 이상하게 짜 놓는다면 B 타입 자리에 C 타입 객체로 대체 할 경우, 어디선가 로직이 깨져버릴 수 있기 때문이다. 이는 Java 에서는 extends 를 통해서 서브타이핑이 가능하긴 하지만, supertype 의 behavior 에 대한 보장은 없기 때문이다. 이와 관련해서는 다음 포스팅에서 이어 서보겠다
- 리스코프 치환원칙은 다음 포스트에서 이어질 "subtyping" 에 초점을 둔 원칙으로 보인다.
참조
https://en.wikipedia.org/wiki/Is-a
'Java' 카테고리의 다른 글
ConcurrentModificationException 은 어디서, 언제 throw 되는걸까? (0) | 2023.04.12 |
---|---|
Aggregation 과 Composition 개념 (0) | 2023.03.24 |
Java 에서 Stack 구현체로는 무엇을 사용해야할까?(feat_Java로 코딩테스트 문제 풀기) (0) | 2022.09.02 |
record 의 생성자를 private 으로 만드는 것이 불가능한 이슈 (0) | 2022.08.23 |
[Java] method final parameter ? (0) | 2022.07.27 |