객체지향 : 다형성 - 메서드 오버라이드 (Method Override)
앞서 객체지향의 4대 특성 중 추상화, 캡슐화, 상속은 다루어 보았다.
이번에는 마지막으로 다형성에 대해 알아볼 것이다.
아래 예제를 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
using System;
namespace example4
{
class Program
{
static void Main(string[] args)
{
Life life = new Life();
Human human = new Human();
Fish fish = new Fish();
life.Move();
human.Move();
fish.Move();
}
}
class Life
{
public void Move()
{
Console.WriteLine("움직인다.");
}
}
class Human : Life
{
public void Move()
{
Console.WriteLine("직립보행.");
}
}
class Fish : Life
{
public void Move()
{
Console.WriteLine("헤엄친다.");
}
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
부모 클래스 Life와 Life클래스를 상속받는 자식 클래스 Human, Fish 클래스가 있다.
세 클래스 모두 Move() 라는 인스턴스 메서드를 가지고 있다.
이 경우, 각 인스턴스로 Move() 메서드를 호출하면 자신의 클래스 내에 정의된 Move() 메서드를 실행한다.
따라서 이 프로그램의 출력 결과는 다음과 같다.
움직인다.
직립보행.
헤엄친다.
계속하려면 아무 키나 누르십시오 . . .
이 코드는 컴파일하는데 오류는 없지만 경고는 뜨는데 그 내용은 다음과 같다.
만약 자식 클래스에 Move() 메서드가 정의되어 있지 않았다면
자식인스턴스.Move() 구문은 부모 클래스의 Move() 메서드를 호출했을 것이다.
허나 부모 클래스에 정의된 메서드와 동일한 이름의 메서드가 자식 클래스에 존재하기 때문에
부모 클래스의 메서드 대신 자식 클래스의 메서드가 호출되는 것이다.
이때 부모 클래스의 메서드는 숨겨진다.
그냥 둬도 잘 작동하지만, 컴파일러는 이런 중복된 이름의 메서드에 new 키워드를 붙여줄 것을 경고하고 있다.
붙이든 안 붙이든 그것은 자유지만, 메서드 오버라이드와 차이점을 두기 위해 나는 붙여주겠다.
자식 메서드는 부모 메서드로 암시적 형변환이 가능하기 때문에 다음과 같은 클래스와 메서드를 구현할 수 있다.
class Moving
{
public void LetMove(Life thing)
{
thing.Move();
}
}
이것은 이렇게 사용될 수 있다.
Moving moving = new Moving();
moving.LetMove(life);
출력 :
움직인다.
계속하려면 아무 키나 누르십시오 . . .
그런데 LetMove() 메서드의 매개변수로 human이나 fish를 넘겨주면 어떨까?
Moving moving = new Moving();
moving.LetMove(life);
moving.LetMove(human);
moving.LetMove(fish);
출력 :
움직인다.
움직인다.
움직인다.
계속하려면 아무 키나 누르십시오 . . .
원하던 결과는 각각 움직인다/직립보행/헤엄친다 였지만 모두 '움직인다' 라는 결과가 나왔다.
이것은 자식 인스턴스가 부모 타입으로 형변환되어 넘겨졌기 때문인데
이런 상황에서도 자기 자신의 형태를 유지하려면 메서드 오버라이드라는 것을 해주어야 한다.
메서드 오버라이드를 위해 virtual과 overried 라는 예약어가 준비되어 있다.
부모 클래스의 Move 메서드에 virtual 예약어를 추가하고, 자식 메서드에는 new 대신 override 예약어를 추가하자.
class Life
{
virtual public void Move()
{
Console.WriteLine("움직인다.");
}
}
class Human : Life
{
override public void Move()
{
Console.WriteLine("직립보행.");
}
}
class Fish : Life
{
override public void Move()
{
Console.WriteLine("헤엄친다.");
}
}
이 작업만 해주어도 출력이 다음과 같이 바뀐다.
움직인다.
직립보행.
헤엄친다.
계속하려면 아무 키나 누르십시오 . . .
이때 부모 클래스의 메서드가 자식 클래스에 의해 재정의(override)되었다고 한다.
이로써 Move 메서드는 다형성을 가지게 되었다.
이전 포스팅에서 모든 클래스는 Object 클래스를 상속받는다고 했다.
그리고 Object 클래스의 메서드 중 하나인 ToString 메서드는 virtual로 정의되어 있다.
즉 다음과 같은 짓이 가능하다.
class Human : Life
{
override public void Move()
{
Console.WriteLine("직립보행.");
}
public override string ToString()
{
return "Homo sapiens"; // 사람의 학명
}
}
ToString 메서드를 오버라이드.
이렇게 호출해보면
Console.WriteLine(human.ToString());
이렇게 출력된다.
Homo sapiens
계속하려면 아무 키나 누르십시오 . . .
다음 포스팅에서는 메서드 오버로드를 배워보자.
'C#' 카테고리의 다른 글
[C# / 게임] 은행 게임 만들어보기 (객체지향 정리) (0) | 2020.01.16 |
---|---|
[C# / 객체지향] 8. 다형성 - 오버로드 (Method Overload) (0) | 2020.01.08 |
[C# / 객체지향] 7. 클래스 상속 (class inheritance) (0) | 2019.12.17 |
[C# / 객체지향] 6. 캡슐화와 정보 은닉 (0) | 2019.12.16 |
[C# / 객체지향] 5. 네임스페이스(namespace) (0) | 2019.12.15 |