클래스는 틀이고 객체는 찍어낸 것이다
Esc

    클래스는 틀이고 객체는 찍어낸 것이다

    –C#기초

    지금까지 데이터는 변수에, 하는 일은 메서드에 따로 두었습니다. 개 두 마리를 다룬다고 해 봅시다.

    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() { ... } } 가지고 있는 것 필드 할 수 있는 것 메서드
    데이터와 기능이 한 상자 안에 있다.
    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 도 클래스였습니다.