📕 1. 객체지향 개요
📄 1. 객체지향
1). C 같은 언어대신 C++, Java, C#를 쓰는 이유?
C#으로 게임를 만들어본 경험에서 나온 생각을 기술해보겠다. 궁극적으로 C보다 생산성이 높아지기 때문이다.
이건 C언어를 써보고 접근해야 다음 장점이 왜 장점인지 알 것이다. 처음부터 OOP 기반 언어를 쓰면 이게 기본인줄 알겠지..
1. 추상적인 요소와 다형성은 중복 코드를 막고 변경에 강한 개발을 가능케 해준다.
2. 상속은 확장된 기능을 가진 요소를 만들기 유용하고 다형적 타입 판별에 도움을 준다.
3. 무분별한 정보 의존을 줄여주고 타입 체크로 메모리 안정성에 기여한다.
4. 파일 단위가 아닌 코드 단위의 서브 프로그램 제작이라는 관점에서 직관적인 개발이 가능케 한다.
① 타입 유연성
- 추상적인 요소와 부모 자식간 캡슐화 : "추상적인 대상에 의존하면 구체적인 대상이 어떻게 구현되었는지 몰라도,
동일한 로직을 일괄 처리할 수 있고, 기능 변경에도 유연하다." - 이점이 중복 코드를 방지하고, 로직 구조에 변경이 없이 수월한 수정과 변경이 가능하다.
② 재사용성
- 상속 : "이미 구현된 대상을 기반으로 기능을 확장할떄, 거의 비슷한 로직을 수행하는 대상을 만들기 유용하다.
이 점은 C는 하지 못했었지만, Has-A 관계로 구현체의 포함 방식은 가능했다.
상속의 의미는 내가 생각할떄, 추상적인 대상의 성격을 부여해 줘서 다형성 달성에 도움을 줌 이라고 생각한다.
③ 안전한 개발
- 캡슐화 : 접근 제어자(public, protected, private)로 무분별한 의존을 줄여 준다.
따라서 기능 사용자 입장에서 불필요하거나 잘못된 참조/수정을 방지하여 안전한 개발이 가능해 진다. - 위험한 타입 캐스팅 방지 : C의
void*
캐스팅으로 다형적인 동작을 수행할 수 있는 방법이 있었다.
이 점은 만약 실제 그 포인터의 구조가 (타입)에 일치하지 않는다면 잘못된 정보로 해석한다든지,
매우 치명적인 데이터 유출이 발생했을 것이다.
다형성
을 compile-time에 타입 체크를 통해 위험한 부분을 언어적으로 방지하고, 안전한 동작을 보장하게 만들었다.
④ 서브 프로그램
- 캡슐화 : "클래스 단위로 멤버와 함수를 묶어서, 마치 작은 프로그램(서브프로그램)처럼 관리한다.
C 구조체 + 함수 포인터보다 직관적이고 생산성이 높아진다."
여기서 C 같은 경우 기존에 멤버와 함수 포인터로 비슷하게 사용 가능했었다.
이로서 하나의 기능을 파일 단위로 구분하는것이 아닌 코드 내용물로도 기능을 분리 하게 되었다는 것은 개발 직관성을 늘렸다고 생각한다. - 하지만 오직 같은 구조체 멤버만으로 작동되는 함수를 만들기 위해 자기 자신을 가르키는
포인터를 늘 첨부해줘야 하므로 이부분을 언어적으로 숨김으로 까먹지 않고 생산성이 증가했다.
2). 변경이란
- 종종,
"자주 변경되는 것", "변경되는 요소", "확장, 수정, 변경이 일어난다."
란 이야기가 보일 것이다.
변경이 지칭하는 바는 바로 런타임/컴파일중 변경도 아닌.. 스크립팅작업 에서 코드 추가하고 제거하고…. 그러한 작업을 말하는 것 같다. - 변할 수 있는 모든 개념은 다음과 같다.
1. 데이터, 2. 메서드, 3. 객체, 4. 자식클래스(서브타입)
그리고 이 개념들은 각각 캡슐화가 되는 타겟이다. - 그런데 아무리 타자를 적게 치고, 타자가 빠르다 하더라도 요즘 에디터단에서도 복붙, 수정이 용이한데?
- 노가다 작업뿐만 아니라 변경됨으로 로직 구조가 깨지는 일이 있을 때,
구현된 로직 구조의 틀을 깨부수지 않고도 확장과 수정, 변경이 용이하다. 는 말에 초점을 맞춰야 한다.
3). 객체 지향 언어를 잘 활용하기 위한 원칙
① SOLID 원칙에 기반하기
- 이걸 잘 지키고, 잘 고민하기만 해도 디자인 패턴에 꼭 의존하지 않아도 된다.
② 공개할 데이터, 공개하지 않을 데이터 구분하기
- 사용자에게 하여금 실수를 줄이고, 상대적으로 변경 여지가 적은 안정적인 부분을 공개하면 코드를 다시 작성하는 일이 줄어든다.
📄 2. Class & Instance
1). 클래스란?
- 데이터 (속성, 상태, 변수, 자료구조) 와 함수 (메서드, 동작) 로 구성된것.
2). 클래스와 인스턴스의 관계?
① Class : 집합
-
인스턴스의 공장, 인스턴스의 집합이다.
-
: Class 집합의 원소로는 Instance가 있다.
② Instance(Object) : 집합의 원소
- Class가 집합이면 이제 Type형태로 이루어진 Product이다.
3). new를 통해 Instance 생성
Class reference = new Class();
① Class
: 자료형이다.
② reference
: 즉 레퍼런스 변수 값 0xFFF.. 저장,
레퍼런스 변수는 Stack 메모리
③ new Class()
: Heap 메모리에 객체를 생성시켜 할당한다.
📕 2. 주요 객체지향 개념
📄 1. 캡슐화
1). 캡슐화
-
파일단위가 아닌 서브 프로그램을 만들 수 있다.
-
변할 수 있는 모든 개념은 다음과 같다. "1. 데이터, 2. 메서드, 3. 객체, 4. 자식클래스(서브타입)"
그리고 이 개념들은 각각 캡슐화가 되는 타겟이다."변경 가능성이 높은 내용(데이터, 메서드, 객체, 서브타입)" 캡슐화를 통해서 숨기고(외부 사용을 막고)
그리고 상대적으로 변경 여지가 적은 안정적인 부분을 공개(외부 사용을 허용)하자 -
위와 같은 타겟들은 확장, 수정, 변경이 일어날것 같아 보이면, 그걸 이제
캡슐화
해줘야 하는것이 -
내부의 로직의 상세 구현을 알필요 없이 공개된 것만 사용하게 유도하도록 접근 한정자를 사용한다.
리모컨 버튼이 어떻게 작동하는지 몰라도 리모컨을 사용할 수 있지? 구현을 몰라도._method_()
하면 사용 가능하다.
- 외부에 공개해야하는것 : 상대적으로 변경 여지가 적은, 혹은 오직 접근하기 위한 역할만 하는것
- Public : Interface같은것.. 혹은 readonly, const, final같은것
- 객체 내부 구현를 안정적인 인터페이스 뒤로 숨겨 캡슐화 한다.
- 과도한 Get, Set은 캡슐화를 무너뜨리는 요인이 된다.
- 내부에 캡슐해야하는것 : "자주 변하는", "변경 가능성이 높은 내부 구현 부분" 이런것들이 캡슐화 되어 캡슐된다.
그렇게 함으로 내부 구현을 부분은 캡슐화를 통해서 숨기고 변경의 영향을 통제해야 한다.- Private, Protected
2). 접근한정자
접근 한정자를 통해 객체의 캡슐화를 구현한다.
호출자의 위치 | public | protected | private |
---|---|---|---|
클래스 내부 끼리 멤버 접근 | ✅ | ✅ | ✅ |
파생 클래스 끼리 멤버 접근 | ✅ | ✅ | ❌ |
비파생 클래스 끼리 멤버 접근 | ✅ | ❌ | ❌ |
public |
protected |
private |
---|---|---|
|
|
|
3). 캡슐화의 종류
위에 언급했던 변할 수 있는 개념 1. 데이터, 2. 메서드, 3. 객체, 4. 자식클래스(서브타입)
각각 캡슐화의 종류를 나눠보자면
① 데이터 캡슐화 : 객체 내부에서만 사용하고 관리되는 캡슐화된 멤버 데이터.
- Product클래스의 멤버로 name은 private이기 때문에 데이터 외부로 부터 캡슐된다.
- Product내부에서만 사용하고 관리되는 캡슐화 된 데이터.
② 메서드 캡슐화 : 내부 행동을 캡슐화 한것으로. 인터페이스를 통해서 공개한다.
로직 구현부로 외부로부터 접근을 의도적으로 막은 녀석들이고
따라서 메서드 수정에 용이하고, 사이드 이펙트가 없으니 변경이 자주 일어나도 된다.
- DiscountPolicy클래스에 정의되어 있는 getDiscountAmount() 메서드는 Protected라, 외부로 부터 캡슐되고,
- DiscountPolicy클래스 내부와 자식클래스에서만 사용되고 관리된다.
① 객체 캡슐화 : 객체와 객체사이 관계가 캡슐화 된 상태이다.
- Product클래스는 DiscountPolicy 타입의 인스턴스 변수 discountPolicy를 합성(Composition)한다.
② 자식클래스(서브타입) 캡슐화(인터페이스 구현)
-
[추상클래스 혹은 인터페이스] : "DiscountPolicy, DiscountCondition"
[Concrete한 자식/서브타입] : "Amount/PercentDiscountPercetage, Coupon/GrageClassCondition"
이 두 관계가 추상적인 관계로
부모클래스나 인터페이스가 자식클래스의 존재를 감추고 있다. - 합성관계로 [인터페이스 | 기반클래스] 타입을 가지는 클래스는
그 타입들의 Concrete한 서브타입들의 존재를 몰라도(어떻게 구현되어 있는지 몰라도). 사용 가능하다.
그리고 이 서브타입 캡슐화는 다형성의 기반이 된다.
📄 2. 상속
- "상속 모체인 클래스" 의 데이터와 함수를 "상속 하는 클래스"가 물려받는다. (재사용)
- 부모의 멤버개수 ≤ 자식클래스의 멤버의 개수
📄 3. 다형성
-
"부모클래스 타입"의 참조 변수로 "자식클래스 타입"의 인스턴스를 참조할 수 있다.
-
C#코드
class Parent { ... } class Child extends Parent { ... } ParentClass P = new ChildClass();
-
-
ParentClass 인스턴스가 다형성으로 자식클래스를 참조할때,
ParentClass에는 없고 ChildClass만이 가지고있는 멤버에 접근할수 있나?? : ❌- ParentClass 타입 변수는 오직 ParentClass 멤버만 접근할 수 있다.
- 그말인 즉슨 비록 자식이 가지고 있다 하더라고 부모에 구현이 안되어 있으면
쓸수가 없다는 말이다.
📄 4. 관계
- Association 연관화
- Aggregation & Composition : Has A
- 집합 : 생명주기가 같지 않음.
- 컴포지션 : 생명주기가 같음.
- Inheritance & Realization 상속 : Is A
- 구체 클래스 상속
- 추상 클래스 & 인터페이스 상속
- Generalization & Specialization
- 일반화 : 공통적인 성질들로 상위 객체를 구성하는것
- 특수화 : 상위 객체를 구체화하여 하위객체를 구성하는것
- 부분-전체(part-whole)' 또는 ’부분(is-a-part-of)' 로 설명되는 연관성
'CS > SW 공학' 카테고리의 다른 글
| 니앙팽이 - 객체지향(OOP) | 2-5 | 구조체 (0) | 2023.02.01 |
---|---|
| 니앙팽이 - 객체지향(OOP) | 2-4 | 클래스의 this & 메소드 체이닝 (0) | 2023.02.01 |
| 니앙팽이 - 객체지향(OOP) | 2-3 | Static (클래스 멤버) (0) | 2023.02.01 |
| 니앙팽이 - 객체지향(OOP) | 2-2 | 접근한정자 (0) | 2023.02.01 |
| 니앙팽이 - 객체지향(OOP) | 2-1 | Class & Instance (0) | 2023.02.01 |