1. Is-A 관계 (상속 - Inheritance)
- 정의: "~은 ~이다"라는 관계임. 자식 클래스가 부모 클래스의 한 종류일 때 성립함.
- 구현: 주로 추상 클래스나 일반 상속을 통해 구현함.
- 예시: Slime is a Enemy. (슬라임은 적이다.)
- 특징: * 부모의 필드와 메서드를 그대로 물려받아 재사용하기 좋음.
- 클래스 간의 결합도가 매우 높음. 부모 클래스가 바뀌면 모든 자식 클래스에 영향을 줌.
- C#은 단일 상속만 지원하므로, Is-A 관계로만 설계하면 구조가 경직될 수 있음.
// 부모 클래스: 추상 클래스로 본질을 정의함
public abstract class Enemy : MonoBehaviour
{
public float health;
// 모든 적이 공통으로 가지는 행위
public abstract void TakeDamage(float amount);
}
// Slime Is-A Enemy (슬라임은 적이다)
public class Slime : Enemy
{
public override void TakeDamage(float amount)
{
health -= amount;
Debug.Log("슬라임이 데미지를 입음");
}
}
2. Has-A 관계 (합성/구성 - Composition)
- 정의: "~은 ~을 가지고 있다"라는 관계임. 한 클래스가 다른 클래스를 멤버 변수로 포함하고 있는 상태임.
- 구현: 클래스 내부에서 다른 객체를 필드(변수)로 선언해서 사용함.
- 유니티 예시: Player has a Weapon. (플레이어는 무기를 가지고 있다.)
- 특징:
- 유연함: 실행 중에(Runtime) 무기를 교체하거나 기능을 갈아끼우기 쉬움.
- 낮은 결합도: 무기 클래스가 바뀐다고 해서 플레이어의 본질적인 코드가 크게 흔들리지 않음.
- 유니티의 컴포넌트 패턴이 바로 이 Has-A 관계의 정석. (GameObject가 Transform, Rigidbody 등을 '가지고' 있는 구조)
// 무기 클래스 (별도의 기능 단위)
public class Weapon : MonoBehaviour
{
public int power = 10;
public void Shoot()
{
Debug.Log("총을 발사함");
}
}
// Player Has-A Weapon (플레이어는 무기를 가지고 있다)
public class Player : MonoBehaviour
{
// 필드로 포함하는 것이 Has-A 관계의 핵심
public Weapon currentWeapon;
void Start()
{
if (currentWeapon != null)
{
currentWeapon.Shoot();
}
}
}