Front-end Developer

0%

개체지향 프로그래밍 (Object Oriented Programming)

절차적 언어의 아쉬운 점

  • 하나의 속성으로 뭉쳐야 할 데이터가 분산되어 각 배열로 관리되게 된다. 예를 들어 몸무게, 키의 속성을 가지는 사람 A, B의 데이터를 관리한다고 할 때, 각각의 속성들이 A라는 사람의 몸무게, 키, B라는 사람의 몸무게, 키로 관리되지 않고, 각각 사람이름 배열, 몸무게 배열, 키 배열로 분산되어 관리된다.
  • 그렇기 때문에 데이터가 많아지면 관리가 힘들어지고, 실수할 가능성이 높아진다.

절차적 언어에 대한 보완점

구조체: 데이터를 그룹으로 묶는다.

  • 그룹을 마치 하나의 변수처럼 사용한다.
  • 생성과 동시에 그룹 안의 모든 데이터는 초기화된다.
  • 기계가 이해하는 데이터 형태는 아니다.
  • 컴파일러가 알아서 그룹 내의 변수를 선언하는 느낌이다.
1
2
3
4
5
6
7
8
9
10
11
//c 언어의 의사 코드
struct Human
{
int age;
float height;
}

//함수 어딘가
Human human;
Human.age = 10;
Human.height = 170.0f;

절차적 언어(struct)의 한계

  • 여전히 데이터와 동작이 분리되어 있다.
  • 함수와 구조체가 여러 개 있다면 어떤 구조체가 어떤 함수와 연관있는지 찾기 귀찮다.

그렇다면 함수도 하나로 그룹화 하면 되지 않을까?


클래스

커스텀하게 만드는 자료형

1. 클래스 만들기

  • 이미 있는 자료형이 아니다.
  • Car라고 하는 새로운 자료형을 직접 만든 것이다.
  • 보통 Car.cs처럼 클래스명을 파일명으로 하고, 별도의 cs파일을 만들어서 클래스를 생성한다.
1
2
3
4
5
6
7
public class Car
{
//Car라는 데이터 타입의 정의
public int Price;
public float Gas;
public string Owner;
}

Price, Gas, Owner와 같이 중괄호 안에 작성된 것을 멤버 변수라 한다. 멤버 변수는 클래스 안에서 자유롭게 사용 가능하다. 멤버 변수는 초기화가 되고, 기본값이 0이다. 참조형(string)의 기본값은 null이다.

2. 개체 만들기

클래스를 사용한다는 것은 클래스를 데이터형으로 사용해서 그 데이터형의 변수를 만들 수 있다는 의미이다. 즉 개체를 만든다는 의미이다.

<클래스 이름> <변수명> = new <클래스 이름>();

1
2
3
//메인함수
//Program.cs
Car car = new Car();
  • 새로운 <클래스 이름>형의 데이터를 만든다.
  • 클래스로 정의된 형에 맞는 구체적인 데이터를 개체라고 한다.
  • C#에서는 new를 통해서만 개체를 만들 수 있다.

3. 개체의 멤버에 접근하기

1
2
3
4
5
6
//메인함수
//Program.cs
Car car = new Car();
car.Owner = "Alex";
car.Price = 2000;
car.Gas = 60.0f;

여기에 동작(함수)를 추가해야 한다.

4. 메서드 - 동작(함수) 추가

메서드(맴버 함수)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Car
{
public int Price;
public float Gas;
public string Owner;

public void Move()
{
Gas -= 0.5f;
Console.WriteLine($"Move! \n (Gas: {Gas}L left)");
}

public void Honk()
{
Console.WriteLine("honk");
}
}
  • 메서드는 개체의 행위들을 말한다.
  • 클래스 안에서 선언한 함수
  • 클래스 안에서 자유롭게 사용할 수 있고, 같은 클래스의 멤버 변수에 접근 가능하다.
1
2
3
4
5
6
7
8
9
//메인함수
//Program.cs
Car car = new Car();
car.Owner = "Alex";
car.Price = 2000;
car.Gas = 60.0f;

myCar.Move();
myCar.Honk();

클래스 생성 후 다음과 같은 경우 문제가 생길 수 있다.

1
2
3
4
5
6
//메인 함수
//Program.cs
Car car = new Car();
car.Gas = 50.0f;

Console.WriteLine($"Price is {car.Price}");

여기서 출력결과는 Price is 0이다. Price가 0이 나온 이유는 개체 생성 후 깜빡하고 데이터를 대입하지 않았기 때문이다. 이처럼 개체 생성 후 깜빡하고 데이터를 대입 안 할 경우 에기치 못한 문제가 발생할 수 있다.

생성자를 쓰면 이러한 문제를 해결할 수 있다.

생성자

개체가 만들어질 때 자동으로 호출되는 특정한 함수

public <클래스명> (<매개변수 리스트>) {}

1
2
3
4
5
6
7
8
9
10
11
12
//Car.cs
public class Car
{
public Car(int price)
{
Price = price;
}
}

//Program.cs
Car car1 = new Car(200); //ok
Car car2 = new Car() //컴파일 오류
  • 생성자 개체를 생성할 때(new) 반드시 호출되는 함수
  • 함수명으로 클래스명을 쓴다.
  • 반환형은 아예 적지 않는다.
  • 생성에 필요한 매개변수를 강제할 수 있다.
  • 생성자는 여러 개를 써도 된다.

하지만 생성자를 써도 문제가 발생할 수 있다.
클래스에 있는 모든 개체가 특정한 동일한 값을 가져야 하는 경우가 있을 수 있다. 예시처럼 Car의 첫 가격이 항상 2000이어야 하는 경우. 아래 코드를 보면 모든 차의 가격이 2000이어야 하는데, 개발자가 실수로 20을 입력한다면 car3의 가격은 20이 된다. 즉 예기치 못한 결과를 얻게 된다.

1
2
3
4
5
6
7
8
9
10
11
public class Car
{
public Car(int price)
{
Price = price;
}
}

Car car1 = new Car(2000);
Car car2 = new Car(2000);
Car car3 = new Car(20);

생성자 안에서 상수를 바로 대입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Car
{
public int Price;
//...

public Car(int price)
{
Price = 500000;
}
}

//Program.cs
Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();

만약 생성자를 만들지 않았다면 기본적인 생성자는 있다고 가정한다. 따라서 car1, car2, car3의 값은 0이다. 이처럼 생성자를 만들지 않았다면 new Car()로 사용할 수 있고, 중간에 Car(int price)와 같은 값을 넣었다면 컴파일이 되지 않는다. 즉 생성자에 어떠한 값을 넣기 시작하면 기본 설정한 생성자는 사라져버린다.

위 방법보다 조금 더 나은 방법은 애초에 Car 클래스에서 개체를 만들 때 5000을 넣어준다. 이렇게 하면 생성자를 만들지 않아도 컴파일 에러가 나지 않고, 모든 Car의 Price는 5000이다.

1
2
3
4
public class Car
{
public int Price = 5000;
}

References
실무 프로그래밍 입문(C#)