클래스는 틀이고 객체는 찍어낸 것이다
지금까지 데이터는 변수에, 하는 일은 메서드에 따로 두었습니다. 개 두 마리를 다룬다고 해 봅시다.
string dog1Name = "바둑";
int dog1Age = 3;
string dog2Name = "초코";
int dog2Age = 5;
void Bark(string name)
{
Console.WriteLine(name + ": 멍멍");
}
돌아가긴 합니다. 문제는 묶여 있지 않다는 것입니다.
dog1Name 과 dog1Age 가 한 마리를 가리킨다는 것은 이름에만 적혀 있습니다.
컴파일러는 모릅니다. Bark(dog2Name) 을 넘기든 Bark("아무거나") 를 넘기든 똑같습니다.
세 마리가 되면 변수를 여섯 개 만들고, 나이 옆에 몸무게를 추가하려면
dog1Weight, dog2Weight, dog3Weight 를 만듭니다.
그리고 어딘가에서 반드시 dog1Name 과 dog2Age 를 같이 쓰는 실수가 납니다.
관련 있는 데이터와 그 데이터를 다루는 코드를 한 덩어리로 묶는 것이 클래스입니다.
클래스는 이렇게 생겼다
class Dog
{
public string Name;
public int Age;
public void Bark()
{
Console.WriteLine(Name + ": 멍멍");
}
}
클래스 안의 변수를 필드라고 합니다. 안의 메서드도 그냥 메서드입니다. 둘을 합쳐 멤버라고 부릅니다.
Bark 안에서 Name 을 그냥 씁니다. 매개변수로 받지 않습니다.
같은 상자 안에 있으니 이미 알고 있습니다. 이게 묶는다는 것의 뜻입니다.
public 은 밖에서 접근할 수 있다는 표시입니다. 이건 뒤에서 제대로 다룹니다.
틀은 하나, 찍어낸 것은 여러 개
붕어빵 틀을 떠올리면 됩니다. 틀 자체는 먹을 수 없습니다. 틀로 찍어낸 붕어빵을 먹습니다.
Dog a = new Dog();
a.Name = "바둑";
a.Age = 3;
Dog b = new Dog();
b.Name = "초코";
b.Age = 5;
a.Bark(); // 바둑: 멍멍
b.Bark(); // 초코: 멍멍
Dog 는 틀이고, a 와 b 가 찍어낸 것입니다. 이 찍어낸 것을 객체라고 합니다.
class Dog { ... } 를 적어 두기만 하면 아무 일도 일어나지 않습니다.
정의를 적어 둔 것이고, 실제로 만드는 것은 new 입니다.
메서드에서 정의와 호출을 나눴던 것과 같은 이야기입니다.
클래스는 메모리에 없습니다. 객체가 메모리에 있습니다.
객체마다 상태가 따로다
찍어낸 것끼리는 남남입니다.
a.Age = 4;
Console.WriteLine(b.Age); // 5, 그대로입니다
a 의 Age 와 b 의 Age 는 다른 자리입니다.
필드는 객체마다 하나씩 생깁니다.
그래서 이제 실수할 자리가 사라집니다.
a.Name 과 b.Age 를 섞어 쓰려면 일부러 그렇게 적어야 합니다.
앞의 변수 여섯 개짜리 코드에서는 실수하는 쪽이 더 쉬웠습니다.
Bark 는 어떨까요. 메서드는 객체마다 복사되지 않습니다. 코드는 하나입니다.
다만 누구의 Bark 인지가 다릅니다. a.Bark() 로 부르면 Bark 안의 Name 은 a 의 것입니다.
마침표는 안으로 들어간다는 뜻이다
a.Name 의 마침표는 “그 안의” 라는 뜻입니다.
사실 처음부터 계속 써 왔습니다.
text.Length // 문자열이 가진 것
list.Count // List 가 가진 것
list.Add(5) // List 가 할 수 있는 것
Console.WriteLine() // Console 이 할 수 있는 것
string 도 List 도 클래스입니다. 이제 그 안이 어떻게 생겼는지 짐작이 됩니다.
Length 는 필드 비슷한 것이고 Add 는 메서드입니다.
우리가 쓰던 것들이 특별한 문법이 아니라 누군가 만들어 둔 클래스였습니다.
클래스로 묶는 기준
같이 움직이는 것들을 묶습니다.
이름과 나이는 개 한 마리에 붙어 다닙니다. 한 마리가 사라지면 둘 다 사라집니다. 그러면 한 상자입니다.
class Player
{
public string Name;
public int Hp;
public int Level;
public void TakeDamage(int amount) { ... }
public bool IsAlive() { ... }
}
Hp 를 깎는 코드가 Player 밖에 있으면, Hp 가 0 아래로 내려가는지
누가 확인할지가 애매해집니다. 안에 두면 TakeDamage 한 곳만 보면 됩니다.
데이터가 있는 곳에 그 데이터를 다루는 코드를 둡니다. 이게 클래스를 쓰는 이유입니다.
정리
- 클래스는 관련 있는 데이터와 기능을 묶는 상자입니다.
- 안의 변수를 필드, 안의 메서드를 그냥 메서드라고 합니다. 합쳐서 멤버입니다.
- 메서드 안에서는 같은 상자의 필드를 매개변수 없이 그대로 씁니다.
- 클래스는 틀이고,
new로 찍어낸 것이 객체입니다. 클래스 자체는 메모리에 없습니다. - 필드는 객체마다 하나씩 생깁니다. 한 객체를 바꿔도 다른 객체는 그대로입니다.
- 마침표는 “그 안의” 라는 뜻입니다.
string이나List도 클래스였습니다.