같은 타입이지만 다양한 동작을 수행할 수 있는 능력!
virtual
키워드로 선언, 자식 클래스에서 필요에 의해 재정의 가능virtual이 선언되어 있을 때, 참조 형태와 실 형태가 다를 경우, 재정의된 override가 실행된다!!
단순히 메서드를 재정의하여 부모의 메서드를 숨겨서 코드를 짠다고 가정해보자.
ex) 아래와 같이 Unit을 상속받는 Marine과 Zergling이 있다.
public class Unit { public void Move() { Console.WriteLine("두발로 걷기"); } public void Attack() { Console.WriteLine("Unit 공격"); } } public class Marine : Unit { } public class Zergling : Unit { public void Move() { Console.WriteLine("네발로 걷기"); } }
그리고 메인에서 아래와 같은 코드를 실행한다고 해보자.
해당 코드를 실행시키면 Marine과 Zergling을 개별적으로 선언했을 때는 문제가 발생하지 않는다.
하지만 아래의 Unit으로 합쳐서 Move를 실행할 경우(부모 클래스로 통합하여 관리할 경우), 의도했던 것과 다른 결과가 나온다.
unit.Move()를 호출하니 Zergling 또한 두발로 걷기가 출력되는 모습.
이는 부모 클래스의 Unit에서 move를 호출해서 자식 클래스의 네발로 걷기가 호출되지 않았기 때문이다.
public class Unit { public virtual void Move() { Console.WriteLine("두발로 걷기"); } public void Attack() { Console.WriteLine("Unit 공격"); } } public class Marine : Unit { } public class Zergling : Unit { public override void Move() { Console.WriteLine("네발로 걷기"); } }
이번엔 위와 같이 코드를 수정해보자.
이 때, virtual은 '내가 Unit의 Move이기는 하지만 참조형이니 실 형태가 다를 수 있다. 실 형태(Marine, Zergling)에 가서 확인해보아라' 라는 의미를 지닌다.
때문에 컴파일러가 virtual을 확인하고 자식 클래스로 와서 상속받은 Move를 확인할 때, 'override'가 선언되어 있으면 해당 실형태로 변환한다.
위의 코드에서 Unit은 참조형, Marine과 Zergling이 실 형태이다. unit.Move()는 virtual로 선언되어 있기 때문에 각자 실 형태를 확인하게 된다. 이 때, Marine은 Move()를 재정의하지 않았기 때문에 그대로 출력되지만, Zergling의 경우는 다르기 때문에 재정의된 Move()가 출력되게 된다.
abstract
키워드를 사용하여 선언, 추상 메서드를 포함할 수 있다.abstract class Shape { public abstract void Draw(); } class Circle : Shape { public override void Draw() { Console.WriteLine("Drawing a circle"); } } class Square : Shape { public override void Draw() { Console.WriteLine("Drawing a square"); } } class Triangle : Shape { public override void Draw() { Console.WriteLine("Drawing a triangle"); } }