[C#] 15. 상속 금지 sealed 키워드


Study/C#  2020. 7. 20. 18:57

안녕하세요. 명월입니다.


이 글은 C#에서의 상속 금지 sealed 키워드에 대한 글입니다.


제가 이전에 클래스를 상속하는 방법에 대해서 소개했었습니다.

링크 - [C#] 12. 클래스 상속과 재정의(override)하는 방법과 override와 new의 차이


클래스를 상속하는 이유는 같은 코드의 작성을 피해서 재사용성을 높으는 것으로 사용하는 것입니다. 그러나 상속을 하므로써 상위 클래스를 직접 참조가 가능해지고 만약 라이브러리를 배포하는 입장에서는 보안이나 여러가지 이유로 반대로 클래스 상속을 막아야하는 경우가 있습니다.

예를 들면 우리가 문자열로 사용되는 String 클래스가 있는데, 이 String 클래스는 다른 클래스와 다르게 소스 상에서 문자열인 리터널을 직접 읽어오는 기능(String a = "test"; new를 사용하지 않고 ""자체가 String으로 자동으로 new로 변환)이 있기 때문에 상속을 하게 된다면 많은 부분에 효율적으로 프로그램을 재구성할 수 있을 것입니다.

그러나 잘 사용하게 되면 좋지만 모든 프로젝트는 설정과 사용대로 움직이지 않기 때문에 프로젝트가 진행되면 분명 처음 의도와 다르게 사용하게 되고 String의 객체를 상속 받은 클래스는 사실 확장 문자열로 만들고 싶었지만 이상한 클래스로 만들어지고 나중에는 엄청 복잡한 프로그램이 될 확율이 큽니다.(C++ Operator와 전처리문의 단점)


그래서 이런 문제를 막기 위한 상속을 금지해야 하는 키워드가 필요한데 그것이 sealed입니다.

using System;
namespace Example
{
  // 클래스에 상속 금지 키워드를 넣는다.
  sealed class Example
  {
    // 출력 함수
    public void Print()
    {
      // 콘솔 출력
      Console.WriteLine("Hello world");
    }
  }
  // Example 클래스를 상속 받는다.
  class SubExample : Example
  {

  }
  class Program
  {
    // 실행 함수
    public static void Main(string[] args)
    {

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

단순하게 클래스 앞에 abstract처럼 sealed 키워드를 넣으면 상속이 금지됩니다.

visual studio에서 에러를 내보내서 컴파일 자체가 안되게 에러가 발생하네요.


위 예제는 클래스의 상속을 막았습니다. sealed 키워드를 함수에 사용하면 클래스는 상속이 됩니다만 재정의가 되지 않습니다.

using System;
namespace Example
{
  // 클래스에 상속 금지 키워드를 넣는다.
  class Example
  {
    // 출력 함수
    public virtual void Print()
    {
      // 콘솔 출력
      Console.WriteLine("Example Print");
    }
  }
  // Example 클래스를 상속 받는다.
  class SubExample : Example
  {
    // Print 함수 재정의 (더이상 재정의를 금지한다)
    public sealed override void Print()
    {
      // 콘솔 출력
      Console.WriteLine("SubExample Print");
    }
  }
  // SubExample 클래스를 상속 받는다.
  class SubExample2 : SubExample
  {
    // Print 함수 재정의 에러
    public override void Print()
    {
      // 콘솔 출력
      Console.WriteLine("SubExample2 Print");
    }
  }
  class Program
  {
    // 실행 함수
    public static void Main(string[] args)
    {
      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

여기서 Example를 SubExample가 상속하고 SubExample2가 다시 SubExample로 부터 상속받았습니다.

여기서 Print 함수를 SubExample가 Example로부터 재정의했고 SubExample2에서 다시 재정의하려고 했는데 SubExample클래스에서 sealed로 재정의를 막았기 때문에 에러가 발생합니다.


그런데 참고로 여기서 override가 아닌 new 키워드를 사용하면 재정의가 가능합니다.

using System;
namespace Example
{
  // 클래스에 상속 금지 키워드를 넣는다.
  class Example
  {
    // 출력 함수
    public virtual void Print()
    {
      // 콘솔 출력
      Console.WriteLine("Example Print");
    }
  }
  // Example 클래스를 상속 받는다.
  class SubExample : Example
  {
    // Print 함수 재정의 (더이상 재정의를 금지한다)
    public sealed override void Print()
    {
      // 콘솔 출력
      Console.WriteLine("SubExample Print");
    }
  }
  // SubExample 클래스를 상속 받는다.
  class SubExample2 : SubExample
  {
    // Print 함수 재정의 에러
    public new void Print()
    {
      // 콘솔 출력
      Console.WriteLine("SubExample2 Print");
    }
  }
  class Program
  {
    // 실행 함수
    public static void Main(string[] args)
    {
      SubExample2 ex = new SubExample2();
      ex.Print();
      SubExample ex1 = ex;
      ex1.Print();
      Example ex2 = ex1;
      ex2.Print();

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

여기서 SubExample2 클래스에서 new를 사용해서 재정의를 했습니다.

new를 하면 재정의를 하는 것이기는 하지만 정확하게는 재정의가 아니고 그냥 함수 이름이 같은 함수를 다시 선언하는 것(?)으로 같은 인스턴스에서 지시자를 SubExample로 바꾸는 것으로 SubExample의 Print함수가 호출됩니다.

링크 - [C#] 12. 클래스 상속과 재정의(override)하는 방법과 override와 new의 차이


여기까지 C#에서의 상속 금지 sealed 키워드에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.