42. 클래스 기타

  • 11 minutes to read

클래스부터 이벤트까지 클래스의 주요 구성 요소를 살펴보았습니다. 이번 강의에서는 클래스의 또 다른 기능들을 몇 가지 정리해보겠습니다.

> // 부분과 정적: 부분 클래스는 클래스를 나눠서 관리하고 정적 클래스는 정적 멤버로 구성됨

42.1. 부분(Partial) 클래스

부분(Partial) 또는 분할 클래스는 아주 오래 전 C# 2.0에서부터 새롭게 제공되는 기능인데 기존의 클래스들은 하나의 CS 파일에 해당 클래스의 멤버를 모두 구현해야 합니다. 하지만, 클래스의 기능이 복잡해짐에 따라서 한 개의 파일에 클래스를 구현함에 제약이 발생하기에 .NET 2.0 기반으로 넘어오면서 클래스를 선언 시 partial 키워드를 붙임으로써 여러 개의 CS 파일로 클래스를 분할해서 만들고 컴파일시에 하나의 클래스로 컴파일 되게 만들 수 있는 기능을 제공합니다.

42.1.1. 부분 클래스를 사용하여 다른 파일에 멤버를 따로 관리

이번에는 동일한 이름의 클래스를 서로 다른 CS 파일로 나눠서 관리하는 방법을 살펴보겠습니다. PartialClassDemo 프로젝트에 FirstDeveloepr.cs, SecondDeveloper.cs, PartialClassDemo.cs 파일의 3가지 파일을 만들고 다음과 같이 코드를 작성합니다.

코드: FirstDeveloper.cs

//[1] Hello 클래스의 첫 번째 파일
using System;

namespace PartialClassDemo
{
    public partial class Hello
    {
        public void Hi() => Console.WriteLine("FirstDeveloper.cs");
    }
}

코드: SecondDeveloper.cs

//[2] Hello 클래스의 두 번째 파일
using System;

namespace PartialClassDemo
{
    public partial class Hello
    {
        public void Bye() => Console.WriteLine("SecondDeveloper.cs");
    }
}

코드: PartialClassDemo.cs

//[?] 부분 클래스를 사용하여 하나의 프로젝트 또는 CS 파일에 
//    동일한 이름의 클래스를 하나 이상 두고 개발할 때 partial 키워드 사용 
namespace PartialClassDemo
{
    class PartialClassDemo
    {
        static void Main()
        {
            //[A] Hello 클래스의 개체로 서로 다른 파일의 멤버들 호출 가능
            var hello = new Hello();
            hello.Hi(); // FirstDeveloper.cs
            hello.Bye(); // SecondDeveloper.cs
        }
    }
}
FirstDeveloper.cs
SecondDeveloper.cs
 

[1]번 코드에는 Hello 클래스의 Hi() 메서드를 두고 [2]번 코드에는 Hello 클래스의 Bye() 메서드를 두고 [A]번 코드처럼 Hello 클래스의 인스턴스를 생성 후 Hi()와 Bye() 메서드에 접근하는 내용을 볼 수 있습니다. 이처럼 부분 클래스를 사용하면 하나 또는 하나 이상의 CS 파일에 동일한 이름의 클래스를 만들고 이를 관리할 수 있습니다.

42.1.2. 부분 클래스를 사용하여 속성과 메서드 멤버를 나눠서 관리

부분(Partial) 클래스를 사용하면 클래스의 여러 멤버를 동일한 이름의 클래스에 나눠서 관리할 수 있는 편리함을 제공합니다. ***코드: ***

// PartialClass.cs
// [?] 부분 클래스(Partial Class): 하나 이상의 동일한 클래스에 멤버를 나눠서 관리 
using System;

namespace PartialClass
{
    // [1] 클래스에 partial 키워드를 붙여 부분 클래스로 설정하고 멤버 제공
    public partial class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    // [2] 부분 클래스의 다른 클래스/파일에 정의된 멤버 사용 가능 
    public partial class Person
    {
        public void Print() => Console.WriteLine($"{Name}: {Age}");
    }

    class PartialClass
    {
        static void Main()
        {
            // [A] 부분 클래스인 Person 클래스의 인스턴스 생성
            Person person = new Person();

            // [B] 멤버가 함께 노출되는 것 확인
            person.Name = "C#";
            person.Age = 20;

            // [C] 출력
            person.Print();
        }
    }
}
C#: 20

PartialClass 네임스페이스에는 [1]번과 [2]번과 같이 동일한 이름을 가지는 Person 클래스가 있습니다. 동일한 이름의 클래스를 가질 수 있는 이유는 클래스 시그니처에 partial 키워드가 제공되기 때문입니다. [1]Person 클래스에는 속성 멤버들만 제공하고 [2]Person 클래스에는 메서드 멤버만 제공해 보았습니다. 프로그램을 실행하는 과정에서 [B]번과 [C]번 내용처럼 서로 다른 곳에 정의된 멤버들이 모두 하나의 인스턴스 개체인 person으로 접근해서 사용할 수 있습니다.  

42.2. 정적 클래스(Static Class)

C#에는 클래스 이름 앞에 static 키워드가 붙는 정적 클래스(Static Class)를 만들 수 있습니다.

정적 클래스는 다음과 같은 특징들이 있습니다.

  • static 키워드를 붙임
  • static 멤버만을 가짐
  • 인스턴스화 될 수 없음
  • 유틸리티 클래스 용도로 사용
  • 팩터리 클래스

42.2.1. 참고: 싱글톤(Singleton)

하나의 프로그램 내에서 하나의 인스턴스 개체만 생성하는 클래스를 싱글톤(Singleton) 클래스라고 합니다. 정적 클래스(Static Class)는 인스턴스화 될 수 없으나, 싱글톤(Singleton)은 인스턴스화됩니다.  

42.3. 필드에 public 붙여 외부 클래스에 공개하기

박용준 강사의 강의에서는 클래스의 구성 요소인 필드에 대해선 무조건 private으로 선언합니다. 다만, 필드도 속성처럼 public으로 해도 전혀 상관없습니다. 그렇게 구성한 코드를 살펴보겠습니다.

코드: PointImperative.cs

> class Point
. {
.     // 필드: public 필드
.     public int x;
.     public int y;
.     // 생성자
.     public Point(int x, int y)
.     {
.         this.x = x;
.         this.y = y;
.     }
.     // 메서드
.     public void MoveBy(int dx, int dy)
.     {
.         x += dx;
.         y += dy;
.     }
. }
> 
> Point point = new Point(0, 0); // 좌표 기본값 설정
> point.MoveBy(100, 200); // 100, 200으로 이동
> Console.WriteLine($"X: {point.x}, Y: {point.y}"); // 100, 200
X: 100, Y: 200

이처럼 public 속성 대신에 public 필드를 사용해도 프로그래밍에는 전혀 지장이 없습니다. 필드는 클래스의 부품 역할을 하기에 이왕이면 꽁꽁 숨기는 것을 권장하기에 private으로 선언하는 것 뿐입니다.

42.4. 함수형 프로그래밍 스타일: 메서드 체이닝

메서드의 반환값을 자신의 클래스 형식으로 지정하면 메서드를 계속 반복해서 호출하는 함수형 프로그래밍 스타일을 제공할 수 있습니다.

코드: PointFunctional.cs

> class Point
. {
.     // readonly 필드
.     public readonly int x;
.     public readonly int y;
.     public Point(int x, int y)
.     {
.         this.x = x; // readonly 필드는 반드시 생성자로 초기화 필요
.         this.y = y;
.     }
.     //[1] 메서드의 반환값을 나 자신(Point)으로 지정 
.     public Point MoveBy(int dx, int dy)
.     {
.         return new Point(x + dx, y + dy);
.     }
. }
> 
> //[A] 함수형 프로그래밍 스타일: 메서드 체이닝
> var p = (new Point(0, 0)).MoveBy(10, 10).MoveBy(20, 20).MoveBy(30, 30);
> $"X: {p.x}, Y: {p.y}"
"X: 60, Y: 60"

이미 우리는 LINQ에서 메서드 체이닝 개념을 학습했습니다. 이러한 메서드 체이닝을 구현하려면 반환 값으로 나 자신의 개체를 반환하면 됩니다. 메서드 체이닝이 사용할 때에는 편리하지만 구현할 때에는 코드의 복잡도가 증가합니다. 나중에 우리는 확장 메서드를 만드는 방법을 배웁니다. 확장 메서드를 사용하면 이번 예제에서 만드는 방법보다 훨씬 간단하게 메서드 체이닝을 구현할 수 있습니다.

42.5. 불변 형식

영어 단어로 Immutable은 '변경 불가능한'의 의미를 가집니다. 프로그래밍에서 불변 형식(Immutable Type)은 개체가 만들어지고 값이 변경되지 않음을 의미합니다. 개체가 생성된 후 변경되지 않아야 프로그래밍 부작용을 줄일 수 있는 경우에 사용합니다.

코드: ImmutableTypeDemo.cs

> //[?] 불변 형식: 개체의 상태는 생성 후 변경되지 않아야 프로그래밍 부작용을 줄임
> public class Circle
. {
.     public int Radius { get; private set; } = 0;
.     public Circle(int radius) => Radius = radius;
.     public Circle MakeNew(int radius) => new Circle(radius);
. }
> 
> //[1] 생성자를 통해서 반지름이 10인 Circle 개체 생성
> Circle circle = new Circle(10);
> $"Radius: {circle.Radius} - {circle.GetHashCode()}"
"Radius: 10 - 62301924"
> 
> //[2] 메서드를 통해서 반지름이 20인 Circle 개체 새롭게 생성
> circle = circle.MakeNew(20);
> $"Radius: {circle.Radius} - {circle.GetHashCode()}"
"Radius: 20 - 37804102"

처음에 생성자를 통해서 생성된 circle 개체는 반지름이 10으로 설정되어 더 이상 변경되지 않습니다. 이렇게 특정 개체가 가지는 속성은 생성 후 변경되지 않도록 설정하면 중간에 속성을 통한 값이 변경되어 잘못된 개체가 되는 걸 방지할 수 있습니다. 만약, 이 개체의 속성을 변경하려면 새로운 메서드를 통해서 새로운 개체를 생성하여 사용하면 됩니다.

42.1. 장 요약

C#에서는 클래스는 여러 모양을 가질 수 있습니다. 그 중에서 이번 강의는 여러 파일에 클래스를 나눠서 관리할 수 있는 부분 클래스와 정적인 멤버로만 구성할 수 있는 정적 클래스를 다루어 보았습니다.

VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com