접근 수정자

클래스 내부에서는 모든 멤버 함수가 이름을 통해 동일 클래스의 다른 멤버에 직접 접근할 수 있습니다.

접근 수정자는 멤버 선언에 사용하는 선택적 접두사로, 프로그램의 다른 코드가 해당 멤버에 접근 가능한지 제한하며 자료형과 메서드 이름 앞에 기입합니다.

필드

접근수정자 자료형 필드명

메서드

접근수정자 반환형 메서드명()
{
    ...메서드 본문
}

다섯 가지 접근 권한

  1. private 비공개
  2. public 공개
  3. protected 보호됨
  4. internal 내부
  5. protected internal 보호 내부

지금은 독자분들이 private와 public만 먼저 학습하면 됩니다. 나머지는 후속 강의에서 다루겠습니다.

수정자 종류와 상관없이 클래스 내부에서는 모든 멤버에 접근할 수 있습니다.

예시를 살펴보겠습니다.

class Robot
{
    public string name;

    int age;

    public void SayHello()
    {
        Console.WriteLine($"Hello everyone my name is {name},I come from Foxdevelop.com");
        Console.WriteLine($"I am {age} years old");
    }

    void AgeUpdate()
    {
        age =  age+1;
    }

    void SayHi()
    {
        SayHello();
    }
}Code language: C# (cs)

위 예시를 보면 public 메서드 SayHello, private 메서드 AgeUpdate와 SayHi, private 필드 age, public 필드 name 가리지 않고 클래스 내부에 존재하면 서로 접근 가능하다는 점을 확인할 수 있습니다.

주의할 점은 서로 호출하는 코드를 작성하면 무한 반복이 발생한다는 것입니다. 예를 들어 다음과 같은 경우입니다.

class Robot
{
    public string name;

    int age;

    public void SayHello()
    {
        Console.WriteLine($"Hello everyone my name is {name},I come from Foxdevelop.com");
        Console.WriteLine($"I am {age} years old");
        SayHi();
    }

    void AgeUpdate()
    {
        age =  age+1;
    }

    void SayHi()
    {
        SayHello();
    }
}Code language: C# (cs)

위 코드에서 SayHi는 SayHello를 호출하고, 다시 SayHello가 SayHi를 호출하는 구조입니다. 상호 호출로 인해 무한 재귀 반복이 발생합니다.

결국 프로그램이 비정상 종료됩니다.

메모리 오버플로우 오류 메시지가 출력됩니다.

또한 필드 초기화 구문에서는 일반 메서드를 직접 호출할 수 없고 정적 메서드만 사용 가능합니다. 인스턴스 메서드는 반드시 객체 인스턴스를 통해 호출해야 하기 때문입니다.

class Robot
{
    public string name;

    int age = GetInt();

    static int GetInt()
    {
        return 1;
    }

    public void SayHello()
    {
        Console.WriteLine($"Hello everyone my name is {name},I come from Foxdevelop.com");
        Console.WriteLine($"I am {age} years old");
    }

    void AgeUpdate()
    {
        age =  age+1;
    }

    void SayHi()
    {
        SayHello();
    }
}Code language: C# (cs)

위 그림처럼 메서드를 정적으로 선언하면 사용할 수 있습니다. 다만 age에 값을 할당할 때 GetInt의 반환값이 계속 변한다면 문제가 발생합니다.

class Program
{
    static void Main(string[] args)
    {
        Robot robot1 = new Robot();
        for (int i = 0; i < 100; i++)
        {
            robot1.WriteAge();
            System.Threading.Thread.Sleep(1000);
        }
    }
}

class Robot
{
    public string name;

    int age = GetInt();

    static int GetInt()
    {
        return DateTime.Now.Second;
    }

    public void WriteAge()
    {
        Console.WriteLine($"I am {age} years old");
    }
}Code language: C# (cs)

위 코드 예시에서 GetInt는 현재 시간의 초 단위 값을 반환합니다. Main 함수 안 for 반복문으로 나이를 출력하는 함수를 100회 실행하고, 출력할 때마다 1초간 대기한 뒤 다음 동작을 진행합니다. 실행해보면 알 수 있는 점이 있습니다.

출력되는 초 값은 초기화 시점에 얻은 값으로 고정됩니다. age 변수를 초기화할 때 GetInt가 한 번 실행돼 예를 들어 45초 값을 가져왔다면, 이후 몇 번을 출력해도 계속 45로 표시됩니다. 지난 단원에서 설명했듯 필드의 초기값은 초기화하는 시점에 확정되어야 하는 규칙이 적용됩니다.

다시 접근 수정자 내용으로 돌아가겠습니다.

간단히 요약하면 수정자에 상관없이 클래스 내부에서는 모든 멤버에 접근할 수 있습니다.

private 비공개 접근

비공개 멤버는 해당 멤버를 선언한 클래스 내부에서만 접근 가능하며 다른 어떤 클래스도 읽거나 수정할 수 없습니다.

클래스 멤버의 기본 접근 수준은 private입니다. 수정자를 생략하는 것은 명시적으로 private를 적는 것과 완전히 동일한 의미입니다.

int MyInt1;              // 암시적 비공개(기본값)
private int MyInt2;      // 명시적 비공개Code language: C# (cs)

public 공개 접근

인스턴스의 공개 멤버는 프로그램 내 모든 다른 객체에서 접근할 수 있으며 직접 public 수정자를 적어 선언해야 합니다.

public int MyInt;        // public 접근 수정자로 표시Code language: C# (cs)

멤버 가시성 규칙

클래스 구조를 설명할 때 클래스 다이어그램을 자주 활용합니다.

클래스 전체는 사각형 박스로 표현하고 멤버는 박스 내부 구역으로 그립니다.

private 멤버: 박스 안에 완전히 감싸여 외부에서 보이지 않음;

public 멤버: 일부 영역이 박스 밖으로 뻗어 나와 전역에서 접근 가능함을 의미.

class Program
{
    int Member1;         // 암시적 private
    private int Member2; // 명시적 private
    public int Member3;  // public
}Code language: C# (cs)

이 장 예시 코드

class C1
{
    int F1;                // 암시적 비공개 필드
    private int F2;        // 명시적 비공개 필드
    public int F3;         // 공개 필드

    void DoCalc()          // 암시적 비공개 메서드
    {
        ...
    }

    public int GetVal()    // 공개 메서드
    {
        ...
    }
}Code language: C# (cs)
  1. 비공개 멤버(F1, F2, DoCalc()): 오직 C1 클래스 내부 코드만 읽고 쓰고 호출할 수 있으며 외부 클래스에서는 전혀 보이지 않음;
  2. 공개 멤버(F3, GetVal()): 프로그램 내 다른 클래스나 객체에서 제한 없이 접근 가능;
  3. 클래스 내부 규칙: C1 내 모든 메서드는 공개/비공개 상관없이 같은 클래스의 모든 필드와 메서드에 접근할 수 있음.

실행 가능한 예시


class Program
{
    static void Main(string[] args)
    {
        Worker worker = new Worker();
        Console.WriteLine(worker.GetHours()); // 정상, 클래스 외부에서 공개 멤버 GetHours 접근 가능
        Console.WriteLine(worker.ReadSavings());//오류, 인스턴스 이름 worker.를 사용해도 클래스 외부에서 비공개 멤버 ReadSavings 접근 불가

        Console.WriteLine(worker.hours); // 정상, 클래스 외부에서 공개 필드 hours 접근 가능
        Console.WriteLine(worker.savings); //오류, 클래스 외부에서 비공개 필드 savings 접근 불가
        Console.WriteLine(worker.age); //오류, 클래스 외부에서 비공개 필드 age 접근 불가
    }
}

class Worker
{
    int age;                // 암시적 비공개 필드
    private double savings;        // 명시적 비공개 필드
    public int hours;         // 공개 필드

    void ReadSavings()          // 암시적 비공개 메서드
    {
        Console.WriteLine(savings);
    }

    public int GetHours()    // 공개 메서드
    {
        return hours;
    }
}Code language: C# (cs)

이제 접근 수정자에 대한 기본적인 이해가 생겼을 것입니다.

접근 수정자

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다