컴퓨터 프로그래밍, 논리 설계 같은 기본 강의들을 수강한 지 시간이 좀 지나서 기초 CS지식을 좀 까먹은 감이 있다. 기억을 떠올릴 겸 정리해 보기로 했다. 자료는 서울대학교 컴퓨터공학부 이영기 교수님의 [컴퓨터 프로그래밍]을 참고했다.
객체
객체지향 프로그래밍에서 클래스의 인스턴스이다. 클래스는 어떤 entity의 method나 attribute(멤버들)를 정의하는 틀이고, 이 틀에 맞게 실제 메모리 공간이 할당된 것을 인스턴스라 한다.
절차지향 프로그래밍에서는 하나의 명령어나 하나의 데이터를 객체라 한다. (몰랐다.)
객체지향 프로그래밍(Object Oriented Programming, OOP)
객체지향 프로그래밍이란 프로그램을 객체들의 상호작용으로 보고, "어떤 객체를 만들 것이며, 그 객체의 역할 혹은 구조를 어떻게 구성해 나갈 것인가"를 목표로 프로그램을 작성하는 프로그래밍 패러다임이다.
사실 oriented라는 것이 지향적인이라는 뜻이지만, 실제로는 "중심"의 의미가 강조되어 사용되는 감이 있고, OOP역시 프로그램을 객체 중심으로, 객체들 간의 상호작용으로 구성한다는 뜻이기 때문에 "객체지향"프로그래밍 보다도 "객체중심"프로그래밍이 좀 더 맞는 표현 아닌가 하는 생각이 든다.
vs
절차적 프로그래밍(Procedual Programming)
절차지향 프로그래밍이라고도 한다. 절차적 프로그래밍은 프로그램을 명령어 혹은 프로시져 호출들의 집합으로 보고, "어떤 기능을 어떤 순서로 수행할 것인가"를 목표로 프로그램을 작성하는 방식이다.
OOP의 특징
1. 추상화
- 여러 개체들 간의 공통된 부분을 뽑아내고, 중요한 부분을 강조하여 일반화하는 것을 추상화라고 한다.
- JAVA를 생각하면서 그냥 "abstract" 키워드를 사용하는 것을 의미하는 것이라 말하는 자료들도 많더라.
- 틀린건 아니지만 클래스를 만드는 행위 자체가 추상화의 정의에 부합한다는 설명이 더 맞는 것 같다. 객체들(인스턴스들)의 공통 부분을 뽑아내고 필요없는 기능을 제하여 중요한 기능을 강조하는 등, 클래스를 만드는 과정이 바로 객체들에 대한 추상화 과정이다.
2. 캡슐화
- 1) 클래스 내에서 Access Modifier 등을 적절히 사용하고 2) attribute와 method를 한데 묶어서 객체 외부에서 일부 attribute를 non-visible하게 만드는(은닉화하는) 것.
- 1) Access Modifier
* public : 모든 클래스에서 접근 가능하다.
* private : 선언된 클래스 안에서만 접근 가능하다.
* default : 같은 패키지 속에서만 접근 가능하다. (기본으로 설정됨)
* protected : 같은 패키지나 자식 클래스에서 접근 가능하다.
- 2) Attribute & method 묶기
: 데이터를 가져와서 어떤 행위를 직접 하는게 아니라, 객체에게 행위를 시키는 것이다. 예를 들어서 Square 클래스가 변의 길이 데이터를 가지고 있으면서 getArea()함수에서 사용한다고 하자. 우리가 굳이 변 길이를 Square 인스턴스에서 받아오거나 하지 않아도 getArea()를 통해 넓이를 구할 수 있다. 우리는 어떻게 넓이가 계산되고 있는지, 변 길이는 얼마인지 등에 직접 접근하지 않게 된다... 은닉화 성공.
- 사용 이유
1) 추상화를 위해 : 내부 구조를 드러내지 않고 method로만 상호작용하므로 추상화가 된다.
2) 보안을 위해 : unauthorized access로부터 데이터를 보호한다.
3) 재사용성, 유지보수성, 유연성 : 프로그램이 캡슐화된 여러 클래스나 인터페이스 등으로 구성되기 때문에 따로 떼어서 수정하거나 옮겨도 서로 영향을 미치지 않는다. 따라서 업데이트/디버깅을 하거나 다른 코드에 떼어 가서 사용해도 문제가 없다.
3. 상속(중요)
- 한 클래스가 다른 클래스의 기능들을 기초로, 여러 기능이나 필드를 추가하여 생성될 수 있는 것이다.
- "A is a B(개는 동물이다)" 와 같이 is-a 관계가 성립할 때, A는 B를 상속할 수 있다.
- 사용 이유
1) 생산성
: 상속의 레벨을 올리면서 프로그램을 점점 복잡하게 만들 수 있다.
2) 재사용성
: 부모 코드를 자식이 사용할 수 있다.
4. 다형성
- 동일한 이름의 서로 다른 함수나 변수를 사용하는 것.
- 자바에서는 오버라이딩, 오버로딩, 타입 캐스팅, 제네릭 등으로 구현되어 있다. C++에서는 연산자 오버로딩도 가능...
https://opentutorials.org/module/516/6127
다형성 - Java
이번 시간에는 다형성(Polymorphism)이라는 주제에 대해서 알아보자. 다형성이란 하나의 메소드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것을 의미한다. 키보드의 키를 통해서 비유
opentutorials.org
기본적인 내용이 담겨 있어서 첨부하지만 전체적으로 잘 읽히는 글은 아닌것 같다.(그냥 철학과라서 유비 싫어해서 그런듯)
OOP의 장점 - 왜 OOP를 사용하는가?
1. 생산성
- 디버깅이 쉽다.
프로그램을 다 만들고 보니 어떤 기능을 수행할 때 치명적인 문제가 발견되었다고 하자. 절차적 프로그래밍에서는 그 기능을 수행하는 부분을 모두 찾아 수정해야 하지만, 객체지향 프로그래밍에서는 해당 기능을 수행하는 객체를 찾아 그 부분만 수정해 주면 된다. 앞서 말한 캡슐화 덕분이다.
- 업그레이드도 쉽다.
위와 동일한 이유에서 그러하다.
- 코드 이해가 쉽다.
인간은 객체를 중심으로 사고한다. 따라서 절차 중심으로 작성된 코드보다 객체 중심으로 작성된 코드를 더 이해하기 쉽다.
- 코드 재사용과 확장이 쉽다.
다른 사람이 작성한 클래스를 뚝 떼 와서 사용할 수도 있고, 상속을 통해 부모 클래스의 기능을 확장하거나 재사용하기도 쉽다.
- 개인적인 경험으로는 좀 더 일의 목표가 구체화되는 경향이 있어 코드를 짜기 쉬운 듯 하다.
2. 보안성
- 객체의 멤버들이 어떤 명령어나 데이터로 구성되는지 알 수 없다.
encapsulation 때문이다.
3. 모듈성
- 복잡한 프로그램 같은 경우에는 기능도 여러 가지인 경우가 많은데, 이 기능들을 절차적으로 구현하면 프로그램이 상당히 복잡해질 것이다. 객체로 분리하여 구현하면 모듈화가 되기 때문에 훨씬 쉽게 프로그래밍 할 수 있으며 분업도 쉽다.
OOP의 단점 - 어떤 경우에서는 OOP를 사용하지 말아야 하는가?
1. 공간과 시간을 많이 잡아먹는다.
- 로우레벨 구조는 어떤지 잘 모르겠지만 객체지향 프로그래밍 언어에서는 추가적인 메모리와 연산이 필요하다고 한다.
- 클래스의 크기가 제각각이기 때문에 정적 메모리 할당이 불가능해지고, 이 때문에 메모리에 Fragmentation이 발생한다. (JAVA가 가비지 콜렉션을 지원하는 이유도 이 때문이다. 이후 가비지 콜렉션이 어떻게 이루어지는지에 대해서도 포스팅하겠다. 시스템 프로그래밍에서 배웠는데 아주 재미있다.)
- 상속 후 오버라이딩을 사용하면 함수의 동적 메모리 바인딩이 필수적이기 때문에(컴파일 타임에 해당 함수의 클래스가 자식 클래스인지 부모 클래스인지 알 수 없음) 런타임 시간 오래 걸린다.
객체지향 5원칙 (SOLID)
1. SRP(Single Responsibility Principle) : 단일 책임 원칙
- 객체는 하나의 책임만을 가진다.
2. OCP(Open-Closed Principle) : 개방-폐쇄 원칙
- 클래스는 확장에는 개방적, 수정에는 폐쇄적이어야 한다.
3. LSP(Liscov Substitution Principle) : 리스코프 치환 원칙
- 부모 클래스의 위치에 자식 클래스를 넣어도 정상동작해야 한다.
4. ISP(Interface Segregation Principle) : 인터페이스 분리 원칙
- 인터페이스는 분리되어야 한다. -> 하위 클라이언트가 사용하지 않는 기능을 포함해서는 안된다.
- 인터페이스를 작게 나누어 클라이언트가 사용할 기능들을 선택적으로 사용할 수 있게 한다.
5. DIP(Dependency Inversion Principle) : 의존성 역전 원칙
- 상위 클래스는 하위 클래스에 의존하면 안된다.
- 추상화는 세부 사항에 의존하면 안된다.
'CS공부 > 자료구조' 카테고리의 다른 글
[자료구조] 이진 탐색 트리(Binary Search Tree) (0) | 2022.10.11 |
---|---|
[자료구조] 힙(Heap) (0) | 2022.10.10 |
[자료구조] Queue와 Stack (0) | 2022.10.10 |
[자료구조] 리스트(List) (0) | 2022.10.10 |
01. 재귀 (0) | 2021.03.05 |
댓글