10/10 인터페이스와 컬렉션

정수현·2024년 10월 22일

C#

목록 보기
3/10

인터페이스

  • 추상 형식이며 클래스나 구조체에서 이를 구현 상속하면 약속된 기능들을 구현해야 한다.
  • 구현 상속이란 자식 클래스가 구현해야 함을 의미한다.

컬렉션

  • 데이터나 개체를 보관할 수 있는 여러 종류의 컬렉션이 있다.
  • 인터페이스 기반으로 정의되어 있다.



인터페이스

  • 추상 형식이므로 구현 상속 해야 한다. (자식 클래스가 부모 인터페이스의 메서드를 재정의)
  • 메서드, 속성, 이벤트, 인덱서를 캡슐화할 수 있다.
  • 장점 : 비슷한 기능이 필요한 여러 형식의 개체를 같은 방법으로 사용할 수 있다.

[클래스]

  • 멤버 필드
  • 생성자
  • 기능 메서드

[추상 클래스]

  • 멤버 필드
  • 생성자
  • 추상 메서드
  • 기능 메서드

[인터페이스] (자식이 구현해야 한다.)

  • 추상 메서드
  • 속성 (미완성)
  • 인덱서 (미완성)
  • 이벤트 (미완성)

인터페이스 정의 및 구현

  • 인터페이스를 정의할 땐, 멤버를 구체적으로 구현하지 않고 캡슐화해야 한다.
  • 묵시적으로 접근 한정이 public이다. (변경 불가)
interface IStudy
{
    void Study();
}

재정의 방식 ① 묵시적 인터페이스 구현

  • 약속된 멤버와 같은 시그니쳐를 갖게 선언한다.
  • public으로 접근 지정해야 한다.
  • 명시적 구현보다 많이 사용되는 방식이다.
class Student : IStudy
{
    public void Study()
    {
    }
}

재정의 방식 ② 명시적 인터페이스 구현

class Student : Istudy
{
    IStudy.Study()
    {
    }
}

다중 인터페이스 구현

  • 부모 클래스는 하나밖에 지정하지 못하지만, 부모 인터페이스는 여러 개를 지정할 수 있다.

  • 클래스 - 다중 상속 X
    인터페이스 - 다중 상속 O
    클래스 1, 인터페이스 1 - 혼용 O (반드시 클래스가 한 개여야 한다.)

interface IStudy
{
    void Study();
}

interface ISleep
{
    void Sleep();
}

class Student: IStudy, ISleep
{
    public void Study()
    {
       Console.WriteLine("학생이 공부를 한다.");
    }
    public void Sleep()
    {
        Console.WriteLine("학생이 잠을 잔다.");
    }
}
  • 위 코드에서는 자식 클래스가 부모 인터페이스인 IStudy, ISleep를 클래스 내부에서 암시적으로 재정의 하고 있다.

부모 클래스와 부모 인터페이스를 둘 다 상속 받아야 한다면

  • 부모 클래스 이름을 맨 앞에 명시해야 한다.
class Man
{
    public void Think()
    {
        Console.WriteLine("생각하다.");
    }
}

interface IStudy
{
    void Study();
}

class Student:Man, IStudy
{
    void IStudy.Study()
    {
        Console.WriteLine("학생이 공부를 한다.");
    }
}
  • class Student : Man, IStudy { }
    클래스와 인터페이스를 동시에 부모 형식으로 사용할 수 있지만, 반드시 클래스명을 먼저 명시한다.

인터페이스 이름 충돌

  • 명시적 인터페이스 구현으로 이름 충돌을 피할 수 있다.
interface IStudy
{
    void Study();
    void Work();
}

interface ITeach
{
    void Teach();
    void Work();
}

class PartTimeTeacher : IStudy, ITeach
{
    void IStudy.Study()
    {
        Console.WriteLine("IStudy : 공부하다.");
    }
    void IStudy.Work()
    {
        Console.WriteLine("IStudy : 수강하다.");
    }
    
    void ITeach.Teach()
    {
        Console.WriteLine("ITeach : 강의하다.");
    }
    void ITeach.Work()
    {
        Console.WriteLine("ITeach : 연구하다.");
    }
}

class Program
{
    static void Main(string [] args)
    {
        PartTimeTeacher teacher = new PartTimeTeacher();
        IStudy istudy = teacher as IStudy; //자식을 부모로 타입으로 변환
        if(istudy != null)
            istudy.Work();
            
        ITeach iteach = teacher as ITeach;
        if(iteach != null)
            iteach.Work();
    }
}
  • 실행 결과 ✔
    IStudy : 수강하다.
    ITeach : 연구하다.

  • 서로 다른 인터페이스에서 같은 이름의 멤버가 캡슐화 되어 있을 땐 명시적 인터페이스 구현을 통해 이름 충돌을 피할 수 있다.

  • IStudy istudy = teacher as IStudy;
    : IStudy 인터페이스를 참조한다.
    명시적 구현 시 형 변환을 통해 따로따로 접근할 수 있다.

인터페이스에 캡슐화 가능한 멤버

  • 인터페이스는 메서드 외에 속성, 이벤트, 인덱서를 멤버로 캡슐화할 수 있다.

다시 공부



컬렉션

  • 인터페이스를 기반으로 구현 약속한다.

  • IList
    : 하나의 개체로 보관하는 컬렉션 (선형자료구조)
    IDictionary
    : 키와 값을 쌍으로 보관하는 컬렉션 (비선형자료구조 (검색목적))

ICollectionStack<T>, Queue<T>
IListList<T>, LinkedList<T>
IDictionarySortedList<K, V>, Dictionary<K, V>


IEnumerable 인터페이스

  • ICollection 인터페이스는 IEnumerable 인터페이스를 기반으로 확장된 인터페이스이다.
  • foreach 구문을 통해 열거하는 작업을 수행할 수 있는 것 또한 IEnumerable 인터페이스를 기반으로 정의되었기 때문이다.

ICollection 인터페이스

  • IList, IDictionary 등 모든 컬렉션의 기반이 되는 인터페이스이다.
  • 위에서도 말했듯 ICollection 인터페이스는 IEnumerable 인터페이스를 기반으로 한다.
public interface ICollection : IEnumerable 
{
    void CopyTo(Array arr, int idx);
    int Count { get; }
}
  • CopyTo() 메서드 : 보관된 요소들을 배열에 복사한다.
    Count 속성 : 보관된 요소의 개수를 가져온다.

Count 속성

  • 보관된 요소 개수를 가져올 때 사용한다.
    배열이나 ArrayList 등의 개체에서 사용 가능하다.
static void Main(string [] args)
{
    //arr 배열
    int [] arr = new int[3] {1,2,3};
    View(arr);
    
    //ar 배열
    ArrayList ar = new ArrayList();
    ar.Add(2);
    ar.Add(3);
    View(ar);
}

private static void View(ICollection c)
{
    Console.WriteLine("Count : {0}", c.Count);
    
    foreach(object obj in c)
        Console.WriteLine("{0} ", obj);
        
    ConeSole.WriteLine();
}
  • 실행 결과 ✔
    Count : 3
    1, 2, 3
    Count : 2
    2, 3

CopyTo() 메서드

  • 보관된 요소들을 배열에 복사하는 메서드
static void Main(string [] args)
{
    int [] arr1 = new int[3] {1, 2, 4};
    int arr2 = new int[5] {11, 12, 13, 14, 15};
    
    arr1.CoptyTo(arr2, 2); //arr2의 세 번째 위치에 arr1 개체의 요소들을 복사한다.
    
    View(arr2);
}

private static void View(Collection c)
{
    Console.WriteLine("Count : {0}", c.Count); //보관된 요소의 개수 출력
    
    foreach(object obj in c)
        Console.WriteLine("{0} ", obj);
    
    Console.WriteLine();
}
  • 실행 결과
    Count : 5
    11, 12, 1, 2, 4

IList 인터페이스

  • 배열과 ArrayList 기반 인터페이스이다.
  • ICollection 인터페이스를 기반으로 한다.

요소 추가

  • int Add(object value);
    : 요소를 추가하는 메서드
    void Insert(int index, object value);
    : 요소를 특정 인덱스 위치에 보관하는 메서드
static void Main(string [] args)
{
    ArrayList ar = new ArrayList();
    ar.Add(1);
    ar.Insert(0, 2);
    ar.Add(3);
    
    foreach(int i in ar)
        Console.WriteLine("{0] ", i);
}
  • 실행 결과 ✔
    2, 1, 3

요소 삭제

  • void Remove(object value); : 요소를 제거하는 메서드
    void RemoveAt(int index); : 특정 인덱스에 보관된 요소를 제거하는 메서드
    void Clear(); : 보관된 전체 요소를 제거하는 메서드
static void Main(string [] args)
{
    ArrayList ar = new ArrayList();
    for(int i=1; i<=4; i++)
        ar.Add(i);
        
    ar.Remove(3);
    ar.RemoveAt(0);
    
    foreach(int i in ar)
        Console.Write("{0} ", i);
        
    ar.Clear();
    Console.WriteLine("\n현재 보관된 요소 개수 : {0}", ar.Count);
}
  • 실행 결과 ✔
    2, 4
    현재 보관된 요소 개수 : 0

기타 기능

  • Contains() : 요소가 보관되어 있는지 확인한다.
    IsFixedSize { get; } 고정 사이즈 속성, 가져오기
    IsReadOnly { get; } 읽기만 가능한지에 대한 속성, 가져오기
static void Main(string [] args)
{
    ArrayList ar = new ArrayList();
    ar.Add(3); //3
    ar.Add(2); //3,2
    ar[0] = 4; //4,2
    
    for(int i=1; i<=5; i++)
    {
        if(ar.Contains(i)
        {
            int index = ar.IndexOf(i); //보관된 인덱스를 얻어온다.
            Console.WriteLine("arr[{0}] : {1}", index, i);
        }
    }
    
    for(int i=0; i<ar.Count; i++)
        Console.WriteLine("ar[{0}] : {1}", i ,ar[i]);
}
  • 실행 결과 ✔
    arr[1] : 2
    arr[0] : 4
    arr[0] : 4
    arr[1] : 2

Dictionary 인터페이스

  • 키와 값을 쌍으로 보관하는 컬렉션들의 기반 형식이다.
  • 키 값은 중복되지 않는다.
  • ICollection 인터페이스를 기반으로 한다.

요소 추가

  • Add() 메서드 : 내부 규칙에 따라 보관될 위치를 결정한다.
    IList 인터페이스와 달리 특정 위치에 보관하는 Insert() 메서드는 제공되지 않는다.

  • void Add(object key, object value);
    : 키와 값을 쌍으로 보관하는 메서드

static void Main(string [] args)
{
    Hashtable ht = new Hashtable();
    ht.Add("사람", "홍길동");
    ht.Add("동물", "강아지");
    
    foreach(DictionaryEntry d in ht)
    {
        Console.Writeline("{0} : {1}", d.Key, d.Value);
    }
}
  • 실행 결과 ✔
    사람 : 홍길동
    동물 : 강아지

요소 삭제

  • Remove() 메서드 : 특정 키에 해당하는 요소를 제거한다.
    IList 인터페이스와 달리 RemoveAt() 메서드를 제공하지 않는다.
  • void Remove(object key); : 특정 키에 해당하는 요소를 제거하는 메서드
    void Clear() : 보관된 모든 요소를 제거하는 메서드
static void Main(string [] args)
{
    Hashtable ht = new Hashtable();
    ht["사람"] = "홍길동";
    ht["동물"] = "강아지";
    ht["식물"] = "수선화";
    
    ht.Remove("사람");
    
    foreach(DictionaryEntry d in ht)
        Console.WriteLine("{0} : {1}", d.Key, d.Value);
    
    ht.Clear();
    Console.WriteLine("현재 보관된 요소 개수 : {0}", ht.Count);
}
  • 실행 결과 ✔
    식물 : 수선화
    동물 : 강아지
    현재 보관된 요소 개수 : 0

  • Hashtable은 요소를 해시 방식으로 저장하기 때문에 출력 순서가 일관되지 않는다. ⇒ "동물"이 먼저 출력될 수도 있고, "식물"이 먼저 출력될 수도 있다.

기타 기능

  • Contains() 메서드 : 특정 키의 요소가 보관되었는지 확인한다.
static void Main(string [] args)
{ 
    Hashtable ht = new Hashtable();
    ht["사람"] = "홍길동";
    ht["동물"] = "강아지";
    ht["식물"] = "수선화";
    
    Console.WriteLine("[ 키 항목 ]");
    foreach(string s int ht.Keys)
        Console.WriteLine("{0}", s);
        
    Console.WriteLine("[ 값 항목 ]");
    foreach(string s in ht.Values)
        Console.WirteLine("{0}", s);
        
    Console.WriteLine("[ 키 : 값 ]");
    foreach(DictionaryEntry d in ht)
        Console.WriteLine("{0} : {1}", d.Key, d.Value);
}
  • 실행 결과 ✔
    [ 키 항목 ][ 값 항목 ] [ 키 : 값 ]
    식물 수선화 식물 : 수선화
    사람 홍길동 사람 : 홍길동
    동물 강아지 동물 : 강아지

IComparable 인터페이스

  • IComparable, IComparer 인터페이스는 개체의 값 비교를 위해 정의되었다.
  • 대표적으로 Sort() 메서드를 제공한다.
  • Sort() 메서드는 기본 형식을 보관한 컬렉션을 오름차순으로 정렬할 수 있다.
    ex) 1차원 배열을 인자로 받는다.
static void Main(string [] args)
{
    int[] arr = new int[10] {10, 9, 8, 6, 4, 2, 1, 3, 5, 7};
    
    Array.Sort(arr);
    foreach(int i in arr)
        Console.WriteLine("{0} ", i);
        
    Console.WriteLine();
}
  • 실행 결과 ✔
    1 2 3 4 5 6 7 8 9 10

  • Sort() 메서드를 사용하기 위해서는 보관하는 요소 형식이 기본 형식이거나 IComparable 인터페이스를 기반으로 정의한 형식이어야 한다.

0개의 댓글