virtual method(가상 함수)
1. abstract(추상) vs virtual(가상)
- abstract(추상) : 선언하는 클래스도 반드시 abstract 클래스. 이 키워드로 정의한 속성이나 메서드는 본문을 정의할 수 없으며 접근 한정자는 public, internal, protected로 선언.
public abstract class TestAbstractClass
{
public abstract int TestAbstractFunc();
}
- virtual(가상) : 정적 클래스를 제외한 모든 클래스에서 사용 가능. 이 키워드로 정의한 속성이나 메서드는 본문을 정의할 수 있으며 abstract와 마찬가지로 접근 한정자는 public, internal, protected로 선언해야 한다.
public class TestClass
{
public virtual int TestAbstractFunc()
{
return 0;
}
}
-> abstract 함수의 자식클래스에서 함수의 재정의는 필수, virtual 함수의 자식 클래스에서 재정의는 선택이다.
2. override와 new 연산자
virtual(가상) 함수를 포함한 클래스를 상속받으면, 자식 클래스에서는 override와 new 연산자를 이용하여 함수의 재정의가 가능하다. (abstract 함수의 경우에는 override를 이용한 재정의만 가능)
override연산자
public class Book
{
public virtual void PrintType() // virtual 함수
{
Console.WriteLine("책");
}
}
public class Novel : Book
{
public override void PrintType() // override 함수
{
Console.WriteLine("소설");
}
}
static void Main(string[] args)
{
Book book = new Novel(); // 자식 객체 생성
book.PrintType(); // '소설' 출력
}
-> 출력 결과: 소설
- override란 상속받은 부모 클래스의 함수를 '재정의' 하는 것을 의미한다.
- Novel로 생성된 객체는 override를 통해 Book의 virtual 함수를 재정의 하게 되고, Book 객체로 '업캐스팅' 되어도 호출시 재정의된 함수로 호출된다.
new 연산자
public class Book
{
public virtual void PrintType() // virtual 함수
{
Console.WriteLine("책");
}
}
public class Novel : Book
{
public new void PrintType() // new 함수
{
Console.WriteLine("소설");
}
}
static void Main(string[] args)
{
Book book = new Novel(); // 자식 객체 생성
book.PrintType(); // '책' 출력
}
-> 출력 결과 : 책
- new란 부모의 함수는 그대로 두면서 동일한 이름의 새로운 함수를 새로 정의하는 것을 의미한다.
- Novel로 생성, 객체는 Book객체로 '업캐스팅' 된다. 생성된 객체는 'Book' 객체임으로 Book의 함수로 호출하게 된다.
* 업 캐스팅(Up casting) : 자식 클래스에서 부모 클래스로 타입 변경, 자동 형변환
* 다운 캐스팅(Down casting) : 부모 클래스에서 자식 클래스로 타입 변경, 명시적 변환
** abstract함수의 경우 override를 통해서만 재정의가 가능한데 이는 위의 overrde와 new이 차이로 다른 부분이다. 몸통이 없는 abstract의 특성 때문에 override로 함수를 완전히 새로 덮어씌우는 것만 가능한 것이다.
override와 new는 자식클래스에서 virtual함수를 새로 정의한다는 점에서 동작이 같지만, 둘의 재정의 특징이 다르기 때문에 경우에 따라 어떻게 동작해야 맞는지에 대한 고민 후 키워드를 결정해야 한다.
'Software Development > C#' 카테고리의 다른 글
[Effective C#] Boxing & Unboxing 정리 (+값타입/참조타입 정리) (0) | 2021.02.11 |
---|---|
[Effective C#] new 한정자 사용 (0) | 2021.01.29 |
[Effective C#] nameof() 연산자 (0) | 2021.01.24 |
[Effective C#] 문화권별로 다른 문자열을 생성하려면 FormattableString을 사용하라 (0) | 2021.01.21 |
[Effective C#] string.Format()을 보간 문자열로 대체하라 (0) | 2021.01.17 |