#추상클래스 #인터페이스 #확장메서드

sejun-Lee·2025년 3월 26일

추상클래스(Architecture)와 인터페이스(Interface)


  • 인터페이스는 추상클래스의 일종으로 특징이 동일함
  • 함수에 대한 선언만 정의하고 이를 포함하는 클래스에서 구체화하여 사용
  • 하지만, 추상클래스와 인터페이스를 통해 얻는 효과는 다르며 다른 역할을 수행함
  • 개발자는 언터페이스와 추상클래스 중 더욱 상황에 적합한 것으로 구현해야 함.

<추상클래스와 인터페이스>


  • 공통점 : 함수에 대한 선언만 정의하고 이를 포함하는 클래스에서 구체화 하여 사용
  • 차이점 : 추상클래스 - 변수, 함수의 구현 포함 가능 / 다중상속 불가
  • .................. 인터페이스 - 변수, 함수의 구현 불가........../ 다중포함 가능

추상클래스(A Is B 관계)


  • 상속 관계인 경우, 자식클래스가 부모클래스의 하위분류인 경우
  • 상속을 통해 얻을 수 있는 효과를 얻을 수 있음.
  • 부모클래스의 기능을 통해 자식클래스의 기능을 확장하는 경우 사용

인터페이스(A Can Do B 관계)


  • 행동 포함인 경우, 클래스가 해당 행동을 할 수 있는 경우
  • 인터페이스를 사용하는 모든 클래스와 상호작용이 가능한 효과를 얻을 수 있음.
  • 인터페이스에 정의된 함수들을 클래스의 목적에 맞게 기능을 구현하는 경우 사용.


  public interface IEnterable	// 인터페이스
{
    void Enter();
}

// 은행은 건물이다 : OK, 상속관계가 적합
public abstract class Building : IEnterable	// IEnterable 상속
{
    public void Enter()
    {
        Console.WriteLine("건물에 들어갑니다.");
    }
}

// 차는 들어갈 수 있다 : OK, 인터페이스가 적합
public class Car : IEnterable
{
    public void Enter()
    {
        Console.WriteLine("차 문을 열고 들어갑니다.");
    }
}

public interface IDamageable
{
    public void TakeDamage(int damage);
}

public class Player
{
    public int hp = 100;
    public void TakeDamage(int damage)
    {
        hp -= damage;
        Console.WriteLine("플레이어가 " + damage + "의 데미지를 입었습니다.");
    }

    public void Jump()
    {
        Console.WriteLine("플레이어가 점프합니다.");
    }
}

public class Monster
{
    public int attackPoint = 10;

    public void Attack(IDamageable damageable)  // (Player player)로도 가능 그럴경우, Jump() 함수까지 사용 가능
    {
        damageable.TakeDamage(attackPoint);
        //damageable.Jump();       // 인터페이스에는 Jump가 정의 되어 있지 않아 사용 불가
    }
}


static void Main(string[] args)
{
    int[] array = new int[5] { 1, 2, 3, 4, 5};

    IReadOnlyList<int> list = array.AsReadOnly();   // 읽기 전용 리스트로 변환



}

static void Test(IReadOnlyList<int> array)
{
    //array[0] = 1;
    //int value = array[0];   // 읽기만 가능하여 수정 등 불가능
}


확장메서드(ExtensionMethod)


  • 클래스의 원래 형식을 수정하지 않고도 기존 형식에 함수를 추가할 수 있음.
  • 상속을 통하여 만들지 않고도 추가적인 함수를 구현 가능.
  • 정적함수에 첫번째 매개변수를 this 키워드 후 확장하고자 하는 자료형을 작성.

public static class Extension       // 확장메서드를 사용하기 위해서는 static 클래스로 선언해야 함.!!!
{
   // 확장메서드는 static으로 선언해야 함. 첫번째 매개변수는 this 키워드를 사용하여 확장하고자 하는 자료형을 선언.
   public static int WordCount(this string text)   
   {
       string[] words = text.Split(' ');
       return words.Length;
   }

   public static int CharCount(this string text, char ch)
   {
       int count = 0;
       foreach (char c in text)
       {
           if (c == ch)
               count++;
       }
       return count;
   }



   public static bool IsOddNumber(this int number)
   {
       return number % 2 != 0;     // 2 로 나눈 나머지가 0 이 아니면 true
   }


   public class Item
   {
       public string name;
   }

   public static Item FindByName(this Item[] inventory, string itemName)
   {
       for (int i=0; i<inventory.Length; i++)
       {
           if(inventory[i].name == itemName)
               return inventory[i];
       }
       return null; // 아이템을 찾지 못했을 경우 null 반환
   }
}

static void Main(string[] args)
{
    string text = "Winner Winner chicken dinner";

    //int count = Extension.WordCount(text);      // 4개의 단어가 있다는 걸 알 수 있음.
    int count = text.WordCount();                // 확장메서드를 사용하여 위와 같은 결과를 얻을 수 있음.
    Console.WriteLine(count);                   // 4

    int charCount = text.CharCount('i');           // 확장메서드를 사용하여 i 문자의 개수를 구할 수 있음.
    Console.WriteLine(charCount);                // 4


    int value = 10;

    bool result = value.IsOddNumber();           // 확장메서드를 사용하여 홀수인지 짝수인지 판별할 수 있음.
    if (result == true)
    {
        Console.WriteLine("정수 {0} 은 홀수입니다.", value);
    }
    else
    {
        Console.WriteLine("정수 {0} 은 짝수입니다.", value);
    }



    Item[] inventory = new Item[10];
    Item potion = inventory.FindByName("포션");        // 확장메서드를 사용하여 아이템을 찾을 수 있음.
}
profile
초보 개발자

0개의 댓글