2022. 3. 21. 16:12ㆍLanguages/C#
*이 글은 <이것이 C#이다> 책을 바탕으로 공부한 글입니다.
1. 부모 클래스의 메소드 숨기자! : new 키워드
부모 클래스로부터 상속 받은 멤버와 이름은 동일하지만 완전히 다른 새로운 멤버로 재정의하고 싶을 때 사용한다. 객체를 생성할 때 사용하는 new 키워드의 의미와는 다르다.
클래스를 작성하다 보면, 만들고 있는 메소드를 나중에 오버라이딩을 할 지 안 할지를 미리 생각한다는 건 쉬운 게 아니다. 왜냐하면, C#에서 오버라이딩을 하기 위해서는 부모 클래스의 메소드를 virtual으로 선언해야 하기 때문이다.
이런 부분까지 전부 설계를 신경써서 작성한다는 것은 경험이 많은 프로그래머가 아니면 어려울 것이다. 그래서 C#에서는 우리 같은 사람들을 위해서, 메소드 숨기기를 지원한다.
class Monster
{
public void Attack()
{
Console.WriteLine("기본 공격");
}
}
class Slime : Monster
{
public new void Attack() // Monster의 Attack()은 숨겨짐
{
Console.WriteLine("점성 공격");
}
}
이렇게 선언을 하고 프로그램을 돌려보면 다음과 같은 결과가 나온다.
Slime slime = new Slime();
slime.Attack(); // "점성 공격" 출력
이렇게 하면, 부모 클래스인 Monster의 Attack() 메소드는 숨겨진 듯한 효과를 보게 된다.
"왜 이런 기능을 넣어놨을까? 오버라이딩과 다를 게 뭐야?"
이런 의문이 들 수 있다. 사실 나도 그랬다. 차이점을 보여주기 위해 다음과 같이 오버라이딩 코드를 추가로 넣었다.
class Monster
{
public void Attack()
{
Console.WriteLine("기본 공격!");
}
public virtual void Skill() // 추가
{
Console.WriteLine("스킬 공격");
}
}
class Slime : Monster
{
public new void Attack()
{
Console.WriteLine("슬라임 점성 공격!");
}
public override void Skill() // 오버라이딩
{
Console.WriteLine("슬라임 스킬 공격!");
}
}
우리는 객체를 참조할 때, 해당 클래스의 참조 변수를 통해 참조를 한다. 하지만, 자식 클래스들이 많을 경우에는 부모 클래스를 통해 자식 클래스를 가리키는 업 캐스팅(Upcasting)을 이용한다.
Monster monster = new Slime();
monster.Attack(); // "기본 공격!" 출력
monster.Skill(); // "슬라임 스킬 공격!" 출력
그렇다. 메소드 숨기기를 해 놓은 경우에는 업 캐스팅으로 출력할 경우, 부모의 메소드가 호출된다.
오버라이딩은 업 캐스팅을 해도 자식 클래스의 메소드가 호출된다.
이게 차이점이라고 할 수 있다. 메소드 숨기기는 말 그대로 진짜 숨겨 놓은 것일 뿐이다. 다형성을 표현하기에는 한계점이 분명 존재한다. 그래서 오버라이딩이 있는 것이다. 그런데 사용해보니, 딱히 new 키워드를 사용하지 않아도 있는 것처럼 작동하는 것 같다.
2. 상속과 오버라이딩을 봉인하다 : sealed 키워드
클래스를 작성하고 나서, 해당 클래스가 의도치 않은 상속이 이루어지는 것을 막기 위해 사용할 수 으며, 이를 봉인 클래스라고 한다.
sealed class Slime
{
...
}
/*
class Bubbling : Slime 상속을 봉인했기 때문에 컴파일 오류가 발생
{
...
}
*/
물론 메소드 오버라이딩 봉인에 대해서도 사용이 가능하다. 모든 메소드를 봉인할 수 있는 것은 아니고, virtual로 선언된 가상 메소드를 오버라이딩한 메소드만 봉인이 가능하다.
class Monster
{
public virtual void Attack()
{
...
}
}
class Slime : Monster
{
public sealed override void Attack()
{
...
}
}
/*
class Bubbling : Slime
{
public override void Attack() 봉인되었기 때문에 오버라이드 불가능
{
...
}
}
*/
그리고 이건 추가로 알아두면 좋을 상식으로, private으로 선언한 메소드는 오버라이딩할 수 없다.
컴파일러는 해당 메소드를 오버라이딩한다고 생각하지 않고, 전혀 없었던 메소드를 선언한다고 간주할 것이다.
'Languages > C#' 카테고리의 다른 글
[C#] const와 readonly 둘 다 읽기 전용인데, 뭐가 다를까? (0) | 2022.03.21 |
---|---|
[C#] 부모 클래스와 자식 클래스 사이의 형변환을 해 보자! (is, as) (0) | 2022.03.21 |
[C#] 부모 클래스를 가리키는 Base 키워드와 생성자 (0) | 2022.03.20 |
[C#] this( ) 생성자와 접근 한정자(Access Modifier) (0) | 2022.03.18 |
[C#] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) + ICloneable 인터페이스 (0) | 2022.03.18 |