순서
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가 실행된다.
'Programming > C#' 카테고리의 다른 글
[Programming][C#] 문법 10. Indexer (0) | 2023.01.13 |
---|---|
[Programming][C#] 문법 9. Parameter(ref, out), Operator Overloading (0) | 2023.01.13 |
[Programming][C#] 문법 7. Partial Class / Method (0) | 2023.01.09 |
[Programming][C#] 문법 6. Deep / Shallow Copy (0) | 2023.01.09 |