
코딩을 어느정도 해보셨던 분들은 객체지향 프로그래밍이라는 단어를 들어보았을 것입니다. 객체지향은 말 그대로 객체의 관점에서 프로그래밍의 방식을 정의한 것입니다. 이와 반대되는 프로그래밍 기법으로는 절차지향이 있습니다.
아래의 예시를 봅시다.
여러분이 책상 브랜드를 운영한다고 가정해봅시다.
요즘은 책상도 개인의 사용환경, 사용패턴에 맞춰서 다양한 제품으로 출시되고 있다보니 구매할때 옵션도 다양해서 각 옵션에 맞도록 제작해서 판매해야 합니다.
어느날 아래와 같이 주문이 들어왔다고 가정해봅시다.
절차지향의 관점에서 각 책상을 제작해보면 아래와 같습니다.
그리고 객체지향의 관점에서 책상을 제작하는 것은 아래와 같습니다.
어떻게 보면 비슷해 보이지만, 2번의 과정에서 가장 큰 차이가 생깁니다.
크기가 1200x600, 상판 색상이 화이트, 프레임 색상이 검정인 책상을 따로 정의
크기가 1400x600, 상판 색상이 메이플, 프레임 색상이 화이트인 책상을 따로 정의
...

이렇게 옵션의 수, 그리고 각 옵션에서 선택할 수 있는 항목이 많거나, 더 늘어난다면 늘어날 때 마다 책상을 따로 정의해야 할 것 입니다.
반대로 객체지향으로 구현할 때는 각기 다른 책상을 따로 정의할 필요 없이 책상이라는 공통된 항목을 하나 정의해서 주문서의 요구에 따라 옵션을 바꾸는 것으로 간단하게 해결이 됩니다.
이처럼 객체의 종류를 정의하고, 이렇게 정의된 유형에 의해 생성된 객체들 간에 상호작용하는 방식을 정의하여, 객체 중심으로 사고를 전개하는 프로그래밍 방식을 객체지향 프로그래밍이라 합니다.
객체지향 프로그래밍에서는 아래와 같은 용어들이 나옵니다.
1. 클래스
2. 메소드
public double GetRectangleArea(double width, double height)
{
return width*height;
}

함수를 쓰는방법은 아래 이미지와 같습니다.

여기서 반환형은 크게 string, int, double, bool, 클래스이름 등이 될 수 있습니다. 그리고 함수는 꼭 값을 반환하지 않아도 되며, 값을 반환하지 않는 함수는 void를 반환형 자리에 적어둡니다. 값을 반환하는 함수일 경우, 코드를 종료할 부분에 return {변수}; 를 붙여서 어떤값을 반환하고 종료한다는 것을 명시해야 합니다.
한편, 일정한 변수를 받아서 해당 값을 참고해서 동작을 수행하고 싶을때는 함수이름 뒤에 붙은 괄호안에 매개변수를 명시하면 됩니다. C#의 특성상 타입을 명시해야 하므로 타입을 적은 변수이름을 아무거나 써준 뒤 함수내에서 해당 변수를 이용해서 일련의 동작을 수행하도록 코드를 작성하면 됩니다.
위 예시에서는 매개변수로 직사각형의 가로길이(width), 세로길이(height)를 받아서 둘의 곱을 반환하는 것으로 직사각형의 넓이를 반환하게 됩니다.
3. 속성
위의 3가지 요소는 객체지향 프로그래밍에서 객체를 정의하는 가장 기본적인 항목들이 됩니다. 이렇게 정의하고 나면 다른곳에서 책상, 의자 라는 클래스를 만들 수 있게 됩니다. 그렇게 만들어진 객체를 인스턴스 라고 부릅니다.

이제 개념을 익혔으니 코드로 클래스를 만드는 법을 보겠습니다.
1. 클래스 정의하기
기본적으로 public class {클래스이름} 의 형태로 써서 클래스를 정의합니다.
(public의 의미는 강의가 진행되면서 이후에 설명할 예정입니다.)
public class Desk
{
}
2. 속성 정의하기
그다음 클래스를 정의하는 영역 안에 속성을 정의합니다. 우선은 가로길이를 먼저 정의합시다.
public class Desk
{
public double Width { get; set; }
}
여기서 get;set;은 값에 대한 접근자로, get;은 get 접근자라 부르며이 속성에 접근해서 값을 얻을 수 있다는 의미입니다.
set;은 set 접근자라 부르며 이 속성에 접근해서 속성의 값을 바꿀 수 있다는 의미입니다.
다양한 책상을 나타낼 수 있게 크기와 관련된 부분(폭, 길이, 높이)과 책상 상판, 그리고 책상의 가격을 정의해 줍니다.
public class Desk
{
public double Width { get; set; }
public double Length { get; set; }
public double Height { get; set; }
public string TableTop { get; set; }
public int Price { get; set; }
}
3. 메소드 정의
그리고 이 책상의 크기와 상판 정보를 원할때 바로 알 수 있도록 메소드를 정의해 줍니다.
public class Desk
{
public double Width { get; set; }
public double Length { get; set; }
public double Height { get; set; }
public string TableTop { get; set; }
public int Price { get; set; }
//책상의 규격 정보 받기
public string GetSize()
{
return $"W : {this.Width}, L : {this.Length}, H : {this.Height}";
}
//책상의 상판 정보 받기
public string GetTableTop()
{
return this.TableTop;
}
//책상의 가격 받기
public int GetPrice()
{
return this.Price;
}
}
한편 여기서 this라는 것이 무엇인지 궁금증이 생길것입니다. 객체 내부에서 값을 참조한다는 의미인데, 쉽게말해
Desk 객체를 desk라고 하나 만들면 이 객체 내에 있는 값을 불러온다는 의미입니다. 만약 TableTop을 "Maple"로 해두었다면, this.TableTop은 "Maple"의 값을 반환한다고 보면 됩니다.
4. 생성자 정의
생성자를 정의해줍니다. 여기서 생성자란, 객체를 생성하기 위한 메소드로, 일반적으로 public 클래스이름() 으로 정의합니다. 그리고 해당 메소드 안에 객체가 생성될 때 어떤 속성을 가진 객체가 만들어질지에 대해 속성을 정의하는 구문을 넣습니다. 여기서 생성자 역시 함수이기 때문에 매개변수를 설정해서, 객체를 생성할 때 부터 내가 설정한 객체가 생성되도록 설정할 수 있습니다.
public class Desk
{
public double Width { get; set; }
public double Length { get; set; }
public double Height { get; set; }
public string TableTop { get; set; }
public int Price { get; set; }
//책상의 크기 정보 받기
public string GetSize()
{
return $"W : {this.Width}, L : {this.Length}, H : {this.Height}";
}
//책상의 상판 정보 받기
public string GetTableTop()
{
return this.TableTop;
}
public int GetPrice()
{
return this.Price;
}
//기본 책상 생성
public Desk()
{
this.Width = 1200;
this.Length = 600;
this.Height = 750;
this.TableTop = "Maple";
this.Price = 80000;
}
//규격과 가격을 직접 입력해서 생성
public Desk(double width, double length, double height, int price)
{
this.Width = width;
this.Length = length;
this.Height = height;
this.TableTop = "Maple";
this.Price = price;
}
//상판만 직접 지정해서 생성
public Desk(string tableTop, int price)
{
this.Width = 1200;
this.Length = 600;
this.Height = 750;
this.TableTop = tableTop;
this.Price = price;
}
//전부 옵션을 지정해서 생성하기
public Desk(double width, double length, double height, string tableTop, int price)
{
this.Width = width;
this.Length = length;
this.Height = height;
this.TableTop = tableTop;
this.Price = price;
}
//Null이 발생되도록 생성
public Desk(bool type)
{
}
}
위 코드에서는 아무 매개변수를 넣지않으면 기본형 책상인 1200600750, 메이플 상판, 80000원인 책상이 생성되게 되어있습니다. 또 여러 조합에 따라 상판과 가격만 바꾸어서 책상을 생성할 수도 있고, 아니면 규격과 가격을 입력하여 책상을 정의할 수 있게 됩니다.
Desk defaultDesk = new Desk();
Console.WriteLine(defaultDesk.TableTop); //Maple 출력
Desk desk2 = new Desk("Ash", 560000);
Console.WriteLine(desk2.TableTop); //Ash 출력
Console.WriteLine(desk2.Price); //560000 출력
...
이렇게 완성된 코드는 아래와 같습니다.
using System;
namespace OOP.Basic.Furnitures
{
//책상 클래스
public class Desk
{
#region 책상의 속성
public double Width { get; set; }
public double Length { get; set; }
public double Height { get; set; }
public string TableTop { get; set; }
public int Price { get; set; }
#endregion
#region 책상관련 메소드
//책상의 크기 정보 받기
public string GetSize()
{
return $"W : {this.Width}, L : {this.Length}, H : {this.Height}";
}
//책상의 상판 정보 받기
public string GetTableTop()
{
return this.TableTop;
}
public int GetPrice()
{
return this.Price;
}
#endregion
#region 책상 생성자
//기본 책상 생성
public Desk()
{
this.Width = 1200;
this.Length = 600;
this.Height = 750;
this.TableTop = "Maple";
this.Price = 80000;
}
//규격과 가격을 직접 입력해서 생성
public Desk(double width, double length, double height, int price)
{
this.Width = width;
this.Length = length;
this.Height = height;
this.TableTop = "Maple";
this.Price = price;
}
//상판만 직접 지정해서 생성
public Desk(string tableTop, int price)
{
this.Width = 1200;
this.Length = 600;
this.Height = 750;
this.TableTop = tableTop;
this.Price = price;
}
//전부 옵션을 지정해서 생성하기
public Desk(double width, double length, double height, string tableTop, int price)
{
this.Width = width;
this.Length = length;
this.Height = height;
this.TableTop = tableTop;
this.Price = price;
}
#endregion
}
}
이제 객체를 다 만들었으니 객체를 만들고 필요한 기능을 사용해 봅시다. 코드를 한곳에 계속 모아두지 않고 가독성을 좋게 하도록 별도의 파일로 구분해서 만들어 줍니다. 프로젝트를 우클릭하여 추가 > 새 항목으로 들어갑니다.

여기서 클래스를 선택하고 원하는 이름으로 입력하여 추가를 합니다. 저는 Furnitures로 했습니다.

그리고 클래스를 정의한 부분은 Furnitures.cs에 옮겨둡니다.

이렇게 하고나면 프로젝트 내의 파일들은 아래와 같이 정리가 됩니다.

Furnitures.cs : 책상을 정의한 코드가 들어있는 곳.
Program.cs : 프로그램을 실행하는 명령들이 들어있는 곳.
지금까지 만들었던 것을 활용해서 고객에게 주문 요청이 들어오면 그에맞는 책상을 생성하는 코드를 만들어 봅시다.
우선 정의한 클래스를 불러올 때 클래스가 정의된 코드를 포함하는 네임스페이스 이름을 using문으로 가져옵니다. 이렇게 불러와야 정의했던 클래스를 다른 코드에서 사용할 수 있습니다.

주문 요청을 받는 부분의 코드는 아래와 같습니다.
using OOP.Basic.Furnitures;
namespace _01_Basic
{
public class GetOrder
{
public static void Main(string[] args)
{
Console.WriteLine("책상 주문하기");
Console.WriteLine("==========");
Console.WriteLine("주문 방법 선택하기");
Console.WriteLine("1. 기본형 책상 구매하기(1200*600*750, 메이플 옵션");
Console.WriteLine("2. 크기만 정해서 구입하기(메이플 상판)");
Console.WriteLine("3. 1200*600 책상의 상판만 바꿔서 구매하기");
Console.WriteLine("4. 전부 커스텀 하기");
Console.WriteLine("==========");
while (true)
{
Console.Write("구매 방법을 선택하세요 : ");
int order = int.Parse(Console.ReadLine());
Console.WriteLine("\n");
Desk desk;
switch (order)
{
case 1:
//기본형 책상 생성
desk = new Desk();
Console.WriteLine("=========");
Console.WriteLine("구매내역");
Console.WriteLine($"규격 : {desk.GetSize()}");
Console.WriteLine($"상판 : {desk.GetTableTop()}");
Console.WriteLine($"가격 : {desk.GetPrice()}");
Console.WriteLine("=========");
break;
case 2:
//커스텀 크기 설정
desk = new Desk("Mahogany", 150000);
Console.WriteLine("=========");
Console.WriteLine("구매내역");
Console.WriteLine($"규격 : {desk.GetSize()}");
Console.WriteLine($"상판 : {desk.GetTableTop()}");
Console.WriteLine($"가격 : {desk.GetPrice()}");
Console.WriteLine("=========");
break;
case 3:
//상판만 변경
desk = new Desk(1200, 600, 750, 100000);
Console.WriteLine("=========");
Console.WriteLine("구매내역");
Console.WriteLine($"규격 : {desk.GetSize()}");
Console.WriteLine($"상판 : {desk.GetTableTop()}");
Console.WriteLine($"가격 : {desk.GetPrice()}");
Console.WriteLine("=========");
break;
case 4:
//전부 커스텀
desk = new Desk(1800, 700, 750, "White", 220000);
Console.WriteLine("=========");
Console.WriteLine("구매내역");
Console.WriteLine($"규격 : {desk.GetSize()}");
Console.WriteLine($"상판 : {desk.GetTableTop()}");
Console.WriteLine($"가격 : {desk.GetPrice()}");
Console.WriteLine("=========");
break;
default:
Console.WriteLine("잘못 입력하였습니다. 다시 입력해 주세요.");
break;
}
Console.WriteLine("주문내역을 더 확인하겠습니까?(Y/N)");
string checkNewOrder = Console.ReadLine();
if (checkNewOrder == "Y")
{
continue;
}
else
{
Console.WriteLine("주문확인을 끝냅니다.");
}
}
}
}
}
전체적인 작동과정은 다음과 같습니다.
다만 위 코드는 몇가지 불편한 점이 있습니다.
그 외에도 몇가지 문제가 있습니다.
다음 강의 부터 이를 하나씩 해결해 보는것을 실습해 보면서 C#의 여러 요소들에 대해 설명하겠습니다.