순서

I. 한정자(Quantifier)설명
II. 한정자(Quantifier) Example

 


 

I. 한정자(Quantifier)설명

 

이 한정자들은 class를 상속 받을 때 사용하는 한정자이다.

 

1. virtual / override 한정자

부모 class에서 다형성의 특징을 위해 자녀 class에게 method의 구현을 맡기는 것.

부모에서도 구현할 수 있고 -> 자녀도 구현 할 수 있다. (virtual - override)
부모에서는 구현할 수 있다 -> 자녀는 구현 해야만 한다. (abstract class)

 

2. sealed 한정자

sealed 한정자는 더 이상의 상속을 막는다는 의미로 사용된다.

만약 class에 sealed가 붙는다면 해당 클래스의 상속을 막는 의미이고
method에 sealed가 붙는다면 하위 class에서 더 이상의 override를 막는 다는 것이다.

 

3. new 한정자 (사실 용도 예시를 잘 모르겠음)

new 한정자는 변수, 함수 등 멤버에 사용할 수 있으며

자녀에 선언된 new 한정자는 부모에 선언된 동일한 멤버를 숨기게 된다.

따라서 new 한정자가 붙은 멤버로 기존 클래스 버전의 멤버를 대신하게 되며
의미상 반대되는 override 한정자와 같이 사용할 수 없다.

https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/new-modifier


+)
부모에서 호출되는 함수들은 자녀class로 넘어와서 호출이 되어야 하는데
자녀 class에서 new를 사용해 완전히 새롭게 정의하기 때문에
넘어오지 못하고 한 단계 위에서 호출이 되는 방식 같다.
seal - override block + 자녀에서 아예 구현을 못함
new - override block + 구현은 할 수 있음
아닐까...


II. 한정자 예시

 

1. virtual / override / sealed

using System;

namespace QualifierApp {
  class A {
    public virtual void a() { Console.WriteLine("A.a()");}
    public virtual void b() { Console.WriteLine("A.b()");}
  }
  class B : A {
    public override void a() {Console.WriteLine("B.a()");}
    public sealed override void b() {Console.WriteLine("B.b()");}
  }
  class C : B {
    public override void a() {Console.WriteLine("C.a()");}
    // seal때문에 b는 구현할 수 없음.
  }
  
  public class CMain {
    static void Main() {
      A CA = new C();
      CA.a(); // C.a()
      CA.b(); // B.b()
      ((B)CA).a(); // C.a()
      ((B)CA).b(); // B.b()
      ((C)CA).a(); // C.a()
      ((C)CA).b(); // B.b() 없으면 위로 올라감
    }
  }
}

C로 메모리를 생성하여 CA는 A를 바라보고 있다.

a(), b() 함수들이 virtual로 선언되어 있어 하위 자녀 class를 탐색하여 실행한다.

a() 는 C의 함수를 실행하고
b() 도 C의 함수를 실행해야 하는데 sealed로 인해 C에서의 구현이 불가능하다.
따라서 상속 한 단계 위인 B.b()가 실행된다. 

 

2.new 한정자

using System;

namespace QualifierApp {
  class A {
    public static int x = 9;
    public void invoke() {Console.WriteLine($"A {x}");};
  }
  
  class B : A {
    new public static int x = 99;
    new public void invoke() {Console.WriteLine($"B {x}");};
  }
  class C : B {
    public override void a() {Console.WriteLine("C.a()");}
    // seal때문에 b는 구현할 수 없음.
  }
  
  public class CMain {
    static void Main() {
      A CA = new C();
      CA.invoke();      // A 9
      ((B)CA).invoke(); // B 99
    }
  }
}

CA 는 A를 가리키고 있고 상속된 B의 invoke()를 실행해야 하지만
new로 막혀있어 A 9 가 실행된다.

B로 Casting 한 뒤에는 의도대로 B 99가 실행된다.

+ Recent posts