개발/C#

[C#] 자습서 6장 - 함수

by Majangnan 2023. 1. 11.

함수는 특정 작업을 분담하는 코드 덩어리에 이름을 붙여 놓은 것이다. 함수를 이용하면 불필요한 반복을 제거하며 필요할 때마다 호출할 수 있고 코드의 재사용성이 향상된다.

메서드

객체지향 기법에서 함수는 전역으로 존재할 수 없고 클래스에 소속된다. 클래스에 소속되는 함수를 '메서드'라고 부르며 객체에 대한 작업을 담당한다(C++ 의 멤버 함수와 같은 의미). 구체적인 동작을 상징하는 짧은 동사와 목적어의 조합으로 이름을 짓는데 WriteLine이 좋은 예이다. 이름을 잘 붙여 놓으면 동작을 쉽게 짐작할 수 있는 것이다.

internal class Program
{
    static public int CalcSum(int from, int to)
    {
        int sum = 0;
        for (int i = from; i <= to; i++)
        {
            sum += i;
        }
        return sum;
    }

    private static void Main(string[] args)
    {
        Console.WriteLine("합계 = " + CalcSum(1, 100));
    }
}

위 예제의 CalcSum 메서드는 두 개의 정수를 입력받아 두 수의 범위에 대한 합을 구해 리턴한다. Main에서 넘겨받은 인수를 통해 from 에서 to까지 루프를 돌며 sum 지역 변수에 누적시켜 범위내의 합계를 구해 반환한다. 일정 범위의 합계를 구한다 했을 때 메서드를 이용하면 메서드만 호출하면 되니 반복이 줄어들고 다른 프로젝트에 재활용하기도 쉽다.

 

프로퍼티

Get/Set

멤버를 외부에서 마음대로 수정할 수 있다면 무결성이 파괴된다. 그래서 액세스 지정자로 주요 멤버를 외부로부터 보호한다.

Time 클래스의 hour, min, sec에는 유효한 범위가 있기 때문에 잘못된 정보( 예) 36시 90분 )를 대입하지 않도록 주요 필드를 숨겨야 한다. 그 대신 필드를 액세스 할 수 있는 Get/Set 메서드를 외부로 공개한다. 다음 예제를 살펴보도록 하자.

internal class Program
{
    class Time
    {
        private int hour, min, sec;
        public Time(int h, int m, int s)
        {
            SetHour(h); SetMin(m); SetSec(s);
        }
        public int GetHour()
        {
            return hour;
        }
        public void SetHour(int aHour)
        {
            if (aHour < 24) hour = aHour;
        }
        public int GetMin()
        {
            return min;
        }
        public void SetMin(int aMin)
        {
            if (aMin < 60) min = aMin;
        }
        public int GetSec()
        {
            return sec;
        }
        public void SetSec(int aSec)
        {
            if (aSec < 60) sec = aSec;
        }
        public void OutTime()
        {
            Console.WriteLine($"현재 시간은 {hour}시 {min}분 {sec}초이다.");
        }

    }

    private static void Main(string[] args)
    {
        Time Now = new Time(12, 34, 56);
        Now.OutTime();
        Now.SetHour(55);
        Now.OutTime();
        Now.SetMin(55);
        Now.OutTime();
    }
}

실행 결과

 

예제를 보면 Hour, min, sec 필드 각 하나당 Get/Set 메서드가 생성되어 있는것을 볼 수 있다. Get 메서드는 필드값을 읽어만 주고, Set 메서드는 조건을 점검하여 정상적인 값만 받아들인다. Main에서 시간에 55를 대입했으나 조건에 맞지 않아 변경이 없는 것을 볼 수 있다. SetMin(55) 는 유효한 값이어서 55분으로 변경된다. 이렇게 필드를 보호하는 목적은 달성했지만 필드 하나당 메서드를 두 개씩 만들기는 번거롭다. 그래서 C#은 이런 Get/Set 메서드의 쌍을 컴파일러가 대신 생성하는 '프로퍼티'를 제공한다.

 

프로퍼티(Property)

지정자 타입 이름 {

         get { return 값; }

         set { 값 변경; }

}

  class Time
    {
        private int hour, min, sec;
        public Time(int h, int m, int s)
        {
            Hour = h; Min = m; Sec = s;
        }

        //프로퍼티(Property). 변수가 아닌 메서드이지만 변수처럼 사용한다.
        public int Hour
        {
            get { return hour; }
            set { if (value < 24) hour = value; }
        }
        public int Min
        {
            get { return min; }
            set { if (value < 60) min = value; }
        }
        public int Sec
        {
            get { return sec; }
            set { if (value < 60) sec = value; }
        }
        public void OutTime()
        {
            Console.WriteLine($"현재 시간은 {hour}시 {min}분 {sec}초이다.");
        }

    }

클래스 안에 프로퍼티로 바뀐 부분만 코드로 옮겨왔다. 필드와 유사하되 {} 블록 안에 get, set 접근자 블록을 추가로 가진다. get 블록은 필드를 읽어주고 set블록은 필드를 변경한다. 프로퍼티를 읽으면 get 접근자를 호출하고 값을 대입하면 set 접근자를 호출한다.

Get/Set 메서드를 제거한 대신 Hour, Min, Sec 프로퍼티를 추가했다. 필드와 같은 이름을 쓸 수는 없어 필드명의 첫 글자를 대문자로 바꾼 명칭을 사용한다. 객체를 사용하는 쪽에서는 프로퍼티를 필드처럼 읽거나 대입한다.

 

프로퍼티의 장점

  • 프로퍼티는 매서드이지만 필드처럼 작동한다. 호출문이 아닌 읽고 쓰는 형태여서 참조문이 간결하다.
  • 프로퍼티는 능동적으로 동작하여 객체의 무결성을 완벽하게 지킨다.
  • 필드는 대입시 값만 바뀌지만 프로퍼티는 값을 바꾸면서 다른 코드도 실행할 수 있어 같이 해야 하는 작업까지 처리한다.

 

 

 

 

 

 

References

http://soen.kr/

 

SoEn:소프트웨어 공학 연구소

 

soen.kr

 

'개발 > C#' 카테고리의 다른 글

[C#] 자습서 8장 - 상속(2)  (0) 2023.01.17
[C#] 자습서 7장 - 상속(1)  (0) 2023.01.13
[C#] 자습서 5장 - 클래스  (0) 2023.01.10
[C#] 자습서 4장 - 제어문  (1) 2023.01.05
[C#] 자습서 3장 - 변수  (0) 2023.01.04

댓글