상속의 교과서 유닛에 대해 구현해보려고 한다.

 

일단 구체적인 사양이 정해지지 않아 내 상상을 좀 가미해야 하는데 만약 사양이 다르게 된다면 그때 수정하는 것으로 하고 일반적인 상황을 상상하여 구현해보도록 하자.

 

상속에 필요한 키워드(예약어)는 abstract, virtual, override, static 등 하나하나 알아보자.

 

1. abstract(추상적인)

메소드앞에 사용할 수 있으며 이 키워드를 사용할 경우 클래스도 abstract키워드를 붙여야한다.
이 예약어를 붙일 경우 뜻 그대로 추상적인 클래스가 되며 이 클래스로는 선언을 하지 못하게된다.

이 클래스를 상속받게 되면 무엇을 구현해야 하는지 알 수 있는 인터페이스 역할을 한다.

(참고로 클래스와 인터페이스의 다른 점은 단 하나의 클래스만 상속받을 수 있으며, 여러개의 인터페이스를 상속 받을 수 있다)

추상 함수는 추상 클래스 내에서 구현할 수 없으며 자식 클래스에서 그 내용을 반드시 구현(override)해야 한다.

당연히 그 내용을 자식 클래스에서 접근해야 하므로 접근자를 private으로 선언할 수 없다. (public과 protected만 가능)

2. virtual (가상의)

abstract와 비교해보자.
비슷한점은 상속받은 클래스 역시 이 함수를 재구현(override) 할수있다.
다른점은 이 함수자체를 해당 클래스에서 반드시 구현을 해야한다. 그리고 해당 클래스에 추상함수가 없이 가상함수만 있다면 클래스앞에 abstract나 virtual키워드를 붙일 필요가없다. 일반적인 클래스에서 가상함수를 선언 할수 있다. 
이 클래스를 상속받은 클래스는 이 가상함수가 이미 부모 클래스에서 구현되어 있으므로 추상함수와 다르게 구현하지 않아도되고 물론 구현해도된다!
만약 자식 클래스에서 이 함수를 구현할때 부모클래스의 함수도 이용하고싶다면 base키워드를 사용하면된다.

마찬가지로 그 내용을 자식 클래스에서 접근해야하므로 접근자를 private으로 선언 할수 없다. (public과 protected만 가능)

3. override (덮어 씌우다)

위의 예약어로 생성한 추상함수나 가상함수를 실제로 구현하는 키워드이다. 부모가 선언한 추상함수를 구현하지 않으면 에러가 나므로 깜빡하고 구현을 안하고 넘어갈 일은 없다. 그러니 특정 클래스를 상속 받는 클래스라면 해당하는 함수들은 구현이 되어있다고 상정후 코딩을 해도된다. 
가상함수를 오버라이딩한다면 부모가 구현한 함수는 사라지고 해당 클래스의 함수만 작동하게되는데 여기서 base키워드를 사용해 부모가 구현한 가상함수를 호출 할 수있게된다.

4. static (정적인)

조금 뜬금 없긴 하지만 클래스간의 상속관계에서 자주보여서 넣어봤다.
이 키워드는 변수앞에 사용하면 단 메모리상에서 사라지지 않는 단 하나의 변수가 만들어진다.
일반적인 변수는 상속을 받으면 변수가 갖는 공간만큼을 해당클래스에서 다시 확보하게 된다.
Unit 클래스의 hp를 상속받은 휴먼과 플랜트는 각각 각자의 hp를 갖게 되는 것이다.
하지만 static으로 선언한 변수는 해당 변수를 가지고있는 클래스들이 모두 한곳의 변수를 바라보게된다.
어떤 한 클래스가 static변수를 수정하게 된다면 모든 클래스의 변수들이 영향을 받게된다.
꽤 위험해보이고 객체지향성을 무너뜨린다. 멀티 스레드 환경에서 락이나 세마포어를 열심히 공부했던 것도 떠오른다. 심지어 메모리상에서 사라지지도 않아 권장 하지 않는다. 
하지만 이게 또 꽤 편리할 때가 있다. 지금당장 떠오르진 않지만 어쨋든 알아 두는걸로!
 
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
public abstract class Unit
{
    protected static int playerIndex = 0;
    protected int hp;
    protected abstract void InitUnit();
    protected virtual void Attack() { }
}
 
public class Human : Unit
{
    // 반드시 구현해야함
    protected override void InitUnit()
    {
         hp = 10;
    }
 
    // 선택적 구현
    protected override void Attack()
    {
        // 부모클래스의 함수 실행
        base.Attack();
    }
}
 
public class Plant : Unit {
    protected override void InitUnit()
    {
        hp = 5;
    }
}
cs

 

+ Recent posts