public interface ITest // I로 시작해야 한다
{
int Hp { get; set; } // 프로퍼티 선언 (접근 제한자 생략 가능)
void Attack(); // 함수 선언 (추상화와 비슷하다)
}
class InterTest : ITest
{
public int Hp { get; set; } // 반드시 public
public void Attack()
{
// 구현 내용
}
}
필드(변수)나 생성자 정의는 불가능하며, 함수, 프로퍼티만 선언할 수 있다.
class는 하지 못하는 다중상속을 가능하게 해준다.
구조체에서도 상속받을 수 있다.
추상화처럼 상속받은 객체는 반드시 멤버(프로퍼티, 함수)를 구현해야한다.
멤버들은 기본 접근 제한자가 public 이며,
상속받은 객체들은 반드시 접근 제한자 public을 붙여야한다.
서로 다른 클래스라도 같은 interface를 상속하면 공통된 동작을 할 수 있다.
public interface IDamagable
{
public void TakeDamage(int damage);
}
IDamagable interface를 선언해 상속받은 객체를 대미지를 입는 객체 속성을 추가한다.public class Player : IDamagable
{
public int hp = 100;
public void TakeDamage(int damage)
{
hp -= damage;
}
public void Jump() { ... }
}
Player 클래스는 TakeDamage() 함수를 반드시 초기화 해야하고,public class Monster
{
public int attackPoint = 10;
public void Attack(IDamagable damagable)
{
damagable.TakeDamage(attackPoint);
}
}
Attack() 함수의 매개변수 타입이 IDamagable 이라,몬스터 인스턴스화.Attack(플레이어 객체);즉, 다른 클래스에도
IDamagable인터페이스를 상속하면,
상속받은 클래스는 공격받을 수 있는 객체가 된다.
| 항목 | 추상 클래스 (abstract class) | 인터페이스 (interface) |
|---|---|---|
| 상속 | 단일 상속만 가능 | 다중 구현(다중 포함) 가능 |
| 변수 선언 | 가능 | 불가능 (필드 X, 프로퍼티는 O) |
| 함수 구현 | 가능 (일부 함수 구현 가능) | 불가능 (C# 8.0 이상은 default 구현 가능) |
| 접근 제한자 | public, protected 등 사용 가능 | 모든 멤버는 기본적으로 public |
| 생성자 | 선언 가능 | 선언 불가 |
| 용도 | Is-a 관계 (상속을 통한 확장) | Can-do 관계 (행동 약속, 능력 부여) |
| 예시 표현 | "슬라임은 몬스터다" | "플레이어는 대미지를 입을 수 있다" |
상속 관계인 경우, 자식 클래스가 부모 클래스의 하위분류인 경우 사용한다.
부모 클래스의 기능을 재사용하고, 자식 클래스의 기능을 확장할 수 있다.
"A는 B이다" 관계를 표현할 때 적합하다.
특정 행동을 포함할 수 있는 경우 사용한다.
ex) 플레이어는 대미지를 입을 수 있다.
인터페이스를 사용하는 클래스는 공통된 동작을 약속하고,
이를 통해 다양한 클래스 간 상호작용이 가능해진다.
인터페이스에 정의된 함수를 클래스에서 목적에 맞게 구현해야 한다.
주로 “~할 수 있다”의 의미를 가질 때 사용한다.
작은 기능을 가진 인터페이스들을 객체에 다중 상속해보니,
마치 엔티티에 컴포넌트를 붙이는 느낌이다.실제 기능이 없는 인터페이스라도 태그처럼 사용할 수 있어서,
유연하게 사용할 수 있는 키워드인 것 같다.