난 대학생 1학년따리고 지금은 3월임

전공과정에 있긴 하지만 대학에서 배운게 하나도 없고, 서론부분조차 뇌피셜이 가득임.. 인간GPT의 대답이라고 생각해줘


서론

객체지향의 시대 이전에 소프트웨어 위기라고 불리는 기간이 있었음

지금 보면 소프트웨어 과학이 정말 발전한것처럼 보이지만, 에니악은 불과 80년전만 해도 현역이였던 컴퓨터야

1세대 프로그래머중 한명인 도널드 커누스는 아직까지 살아있어

어셈블리어조차 없이 전선들고 이리저리 옮기면서 프로그래밍 하는 사람들이 어떻게 크롬을 만들고, 스팀을 만들까?

당연히 천재가 수십명이 나와도 인간인 이상 온 인생을 바쳐도 만들수가 없겠지

물론 어셈블리어도 생기고, C언어도 생겼지만 선배 개발자들은 앞에 쌓인 지식이 하나도 없었고, 숙련도가 부족했기때문에 주어진 시간 안에 클라이언트의 그런 말도 안되는 요구들을 받아들여서 수행할 수 없었음

그 선배들이 이후 수십년간 대가리 깨져가며 코딩하다가 만들어낸 프로그래밍 가이드라인중 하나가 객체 지향 프로그래밍이야


본론

왜 객체같은걸 써먹는지, 상속이라는 헛짓거리는 왜 하는지 설명할게


서론의 결론은 결국 빠르게 개발할 수 있어야 하고, 몇 가지 기능들이 만들어진 뒤에도 추가로 끊임없이 이어서 개발할 수도 있어야 한다는게 가장 중요한 포인트야

코딩을 하거나 아래 글을 읽을 때 항상 생각해야 하는게, 이 코드를 미래에 보강해서 사용하기 좋을지, 원래 있던 코드를 얼마나 멋지게 재활용 했는지가 중요해

새로운 코드를 빠르게 쨔기 위해서 어떻게 해야겠냐는 질문에 대해 선배들은 이미 있는 코드를 재활용하겠다는 생각을 했고, 그렇게 나온 개념이 코드의 재사용성임


어떻게 하면 재활용하기 좋은 코드를 쨜 수 있을까? 어떻게 재활용을 해야할까?

우린 보통 재활용하려고 함수 사용하잖아? 뭐 점과 점 사이의 거리를 구하는 함수 dist(x1, y1, x2, y2)라고 하면 그 안에서도 루트함수를 사용할텐데,

이거 생각해보면 의외로 구현하기 까다로움

라이브러리 없었으면 이걸 일일이 구현하고 있었을테고.. 아무튼 그래서 함수가 굉장히 유용한 문법이지

일단 이렇게 첫번째 아이디어인 함수를 사용하자가 있어


한번 함수를 사용해보자

만약 점과 점 사이의 거리가 아니고, 점과 직선사이의 거리라면 어떨까? 직선의 방정식은 ax+b=y잖아?

그러면 dist함수를 써서 그걸 구하려면 dist(x1, y1, a, b)의 리턴값을 받아오면 될까?

아니겠지? 왜냐면 (x1,y1)(a,b)의 거리는 점과 직선 사이의 거리가 아니니까.

그래서 어쩔 수 없이 dist함수 아이디어를 개선해서 point_line_dist()랑 point_point_dist()함수를 생각하게되는데..

라고하면 이게 뭐하는짓인가 싶잖아? 당연히 dist가 dist(point, point)랑 dist(point, line)으로 각각 따로 기능해야하지 않겠어?


그래서 지금 정말 중요한 아이디어 두개가 나왔는데,

함수 하나가 두가지 이상의 코드로 기능하게 만들자는 것, 그리고 여러 값을 하나의 추상적인 대상으로 묶어서 다루자는 것이 그거야

함수 하나가 여러 방식으로 기능하게 하는걸 오버로드라고 부르고, 추상적인 대상을 객체라고 불러.


여기선 point와 line이 객체일거야. 만물이 객체라는게 그런얘기지

여기서 point는 x좌표와 y좌표라는 속성을 가지고있고, 이걸 캡슐화해서, 자신을 두 수의 나열이 아니라 점이라는 객체로써 바라보도록 유도하고있음

dist(point1, point2)랑 dist(x1,y1,x2,y2)를 비교해보면,

값 두개를 점이라는 대상 하나로 다룰 수 있기 때문에, x1과 y1이 하나의 점을 나타내는 값들이라는게 분명해졌고, 읽는것도 쉬워졌지? 이게 캡슐화의 장점이야. 객체 자체가 가지는 특징이 캡슐화기도 하고..


여기가 클래스 설명하기 가장 좋을것같아서 잠깐 클래스 얘기할게

"point는 x값과 y값을 가지고 있습니다." 라는 설명이 클래스고, point(x, y)나, point(3,7)은 객체야. 클래스는 이게 다임


함수 하나가 여러 방식으로 기능하게 하는걸 함수의 오버로드라고 했잖아?

이걸 함수에게 다형성을 부여했다고 말할 수 있는데,

다형성이 뭐냐면 한 객체가 때에 따라 여러가지 방법으로 해석될 수 있을 때 다형성이 있다고 불림

한가지 함수를 점에도 사용하고, 선에도 사용하고, 원하면 정육면체에도 사용할 수 있고, 문고리와 사람 사이의 거리도 잴 수 있게 만드는걸 봤으니 다형성이 얼마나 좋은 아이디어인지는 금방 알 수 있을거야


선은 좀 예외적이지만.. 한번 생각해보면 점, 문고리, 정육면체, 사람은 전부 좌표를 가진다는 특징이 있어.

이런식으로 같은 특징을 가지는 객체들에서 중복된 코드를 제거하는 방법을 제공하는게 상속이야

위치만을 가지는 객체의 클래스를 IPositional이라고 부르자. IPositional 클래스가 좌표 클래스 coordinate를 포함하게 구성하고 나면, IPositional 클래스에서 상속받은 클래스들은 좌표를 가진다는걸 무조건 보장할 수 있게됨

그러면 클래스 "문고리"에는 좌표값이 있습니다~~하고 클래스에 적어주는 대신, 좌표를 가지는 클래스 문고리가 있습니다!라고 할 수 있는거지. 의사코드로 비교해보고 이어서 말하겠음

DoorHandle

{

public:

color handle_color;

handle_style style;

coordinate position

private:

enum handle_style {turn, push, slide};

}


DoorHandle : IPositional 

{

public:

color handle_color;

handle_style style;

private:

enum handle_style {turn, push, slide};

}


IPositional에서 상속받지 않고 구현된 클래스 DoorHandle에는 큰 단점이 있어

coordinate를 참조할 때 DoorHandle.coord를 써야할지, DoorHandle.position을 써야할지, DoorHandle.pos를 써야할지 전혀 짐작할 방법이 없다는거야

하지만 IPositional에서 상속받은 클래스들은 전부 좌표를 참조할 때 같은 이름을 쓰면 된다는게 보장되지

이정도 왔으면 아마 객체지향적인 코드를 왜 작성하는지는 짐작이 가능할거야.. 아직 부족하다면 엄청 큰 프로젝트를 상상해보자


마지막으로 내가 좋아하는거라서 하나 더 다루겠음

다형성과 상속이 결합되면 정말 강력한 문법이 만들어지는데, 한번 보자

dist함수를 각 사물에 대해서 일일이 오버로드 하는 대신.. dist(IPositional, IPositional) 함수를 작성하면

dist(triangle, rectangle)도, dist(point, cube)도 뭐든간에 dist의 인자로 들어온 객체가 IPositional에서 상속받았다면 함수의 사용이 가능함

객체지향의 세가지 구성요소를 전부 활용하면 이런식으로 존나 꼴리는 함수를 만들 수 있다