내부 구현은 이루어지지만 자기 자신을 인스턴스화 하지 않는다.
일반 클래스 ~ 인터페이스의 중간 단계라고 생각하면 이해가 편하다.
이러한 추상 클래스를 이해하기 위해, 몬스터의 공격 작동을 구현하면서 진행해보자.
코드 추가
public class BaseMonster : MonoBehaviour
{
public float damage = 100f;
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
Attack();
}
}
public virtual void Attack(); //<- 에러!
}
이때 Attack() 함수는 몬스터가 동일하게 가지고 있어야 하지만, 그 기능은 몬스터마다 달라야 한다.
= 내부 구현을 하지 않아야 한다.
하지만 virtual 을 사용하는 순간 내부 구현이 강제된다.
이처럼 어느 정도의 내부 구현은 필요하지만, 일부에서는 선언만 필요로 할 때
추상 클래스를 사용한다.
기본 내부 구현을 이루어 놓은 상태에서 자식 클래스가 덮어 씌울 수 있게 함
: 클래스/함수 앞에 'abstract' 키워드를 붙여서 사용한다.
'추상적인' 이라는 뜻을 가지고 있다.
자체적으로 내부 구현( 위 코드에서의 Update() ) 를 만들 수도, 선언만 ( 위 코드에서의 Attack() ) 만들어 놓을 수도 있다.
선언만 만들어 놓을 수 있기에 인스턴스화는 불가능하지만,
내부 구현을 만들어 놓을 수도 있어 자식클래스에서 상속받아 사용하게 할 수도 있다.
코드 추가
//BaseMonster 클래스 앞에, Attack() 함수의 virual 을 abstract로 변경
public abstract class BaseMonster : MonoBehaviour
{
public float damage = 100f;
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
Attack();
}
}
public abstract void Attack();
}
----------------------------------------
//새로운 스크립트
public class Goblin : BaseMonster
{
public override void Attack()
{
Debug.Log("고블린 공격 : " + damage);
}
}
에디터 설정
위 코드로 만든 Goblin 스크립트를 컴포넌트로 할당
실행 결과
정상적으로 동작한다
이때 damage 수치 100은 BaseMonster에게서 상속받은 수치이다.
Q. 실제 플레이를 하게 되면 몬스터마다 damage 수치가 달라야 할텐데,
BaseMonster에서 상속받으면 이 수치가 고정되는게 아닌가?
A. damage 변수는 public 선언이기 때문에 Inspector 창에서 바꿀 수 있다.
그럼 다른 몬스터도 추가해보자.
이번에는 고블린에 이어 오크 몬스터를 만들어보려고 한다.
코드 추가
public class Oak : BaseMonster
{
public override void Attack()
{
Debug.Log("오크 공격 : " + damage);
}
}
에디터 설정은 기존 고블린과 동일한 작업을 수행한다.
마찬가지로 정상적으로 작동한다.
이때 고블린과 오크는 같은 부모, BaseMonster를 상속받았다.
여기서, 지난 파트에서 배운 점을 활용할 수 있다.
바로 '다형성' 말이다.
BaseMonster 클래스로 두 객체를 한번에 관리할 수 있다.
코드 추가
public class Test : MonoBehaviour
{
public BaseMonster[] monsters;
private void Start()
{
for(int i = 0; i< monsters.Length; i++)
{
Debug.Log(monsters[i].gameObject.name);
}
}
}
에디터 설정
실행 결과
정상적으로 출력되는 모습을 볼 수 있다.
이 과정처럼 같은 부모를 상속받는 객체들은 부모가 일반 클래스인지, 추상 클래스인지 상관없이 부모 클래스의 배열을 통해 한번에 관리할 수 있다.
: 다형성 특징 활용
하지만 여기서 BaseMonster 스크립트를 컴포넌트로 추가하려고 하면?
스크립트 추가가 불가능하다.
위에서 언급한 Abstract 추상 클래스는 인스턴스화가 불가능하다 라는 특징 때문이다.
추상 클래스
1. 내부 구현을 이루어놓을 수도, 선언만 사용할 수도 있는 클래스
2. 자기 자신은 인스턴스화가 불가능하다.
3. 클래스와 함수 앞에 'abstract' 키워드를 사용한다.
4. 자신을 상속받는 자식 클래스에 다형성의 특징을 활용할 수 있다.
#17. 프로퍼티(Property) (0) | 2024.08.05 |
---|---|
#15. 인터페이스(Interface) (0) | 2024.08.05 |
#14. 오버라이드(Override) (0) | 2024.08.03 |
#13. 다형성 (0) | 2024.08.03 |
#12. 상속 심화 (0) | 2024.08.02 |