|
조별 스터디 | |||
이 름 |
유 진명 |
일 시 |
2010-11-02 |
예상 시간 |
3 |
소요시간 |
4 |
주 제 명 |
인터페이스와 컬렉션 |
C#을 이용한 인터페이스 정의하기
인터페이스는 의미론적으로 관련된 추상 멤버들의 집함에 이름을 붙여 놓은 것이다. 인터페이스에 정의되는 멤버의 개수는 모델링하고자 하는 동작에 달려있다.
인터페이스 정의의 예>
public interface IPointy { byte GetNumberOfPoints(); } |
인터페이스를 지원해서 C# 클래스의 기능을 확장하려면, 형식 정의 부분에 쉼표로 구분해서 해당 인터페이스의 목록을 적으면 된다. 클래스를 상속 받을 경우 클래스의 이름이 먼저 나와야 한다.
public class Shape { public string PetName; public Shape() { } public Shape(string name) { this.PetName = name; } virtual public void Draw() { } } public interface IPointy { byte GetNumberOfPoints(); }
public class Hexagon : Shape, IPointy { public Hexagon() { } public Hexagon(string name) : base(name) { } public override void Draw() { Console.WriteLine("Drawing{0} the Hexagon", PetName); } public byte GetNumberOfPoints() { return 1; } } |
객체 레벨에서 인터페이스 멤버 호출하기
해당 인터페이스에 의해서 제공되는 기능과 상호작용 할 수 있는 가장 간단한 방법은 원하는 메소드를 객체 레벨에서 직접 호출 하는 것이다.
Hexagon hex = new Hexagon(); Console.WriteLine("Points : {0} ", hex.GetNumberOfPoints()); |
인터페이스 참조 얻기:명시적 형변환
Hexagon hex = new Hexagon("Bill"); IPointy itfpt = (IPointy)hex; Console.WriteLine("Points : {0} ", itfpt.GetNumberOfPoints()); |
인터페이스 참조 얻기 : “as” 키워드
Hexagon hex2 = new Hexagon("Peter"); IPointy itfpt2 = hex2 as IPointy; if (itfpt2 == null) Console.WriteLine("Not Pointy.."); else Console.WriteLine(itfpt2.GetNumberOfPoints()); |
인터페이스 참조 얻기 : “is” 키워드
Hexagon hex3 = new Hexagon(); if (hex3 is IPointy) Console.WriteLine(hex3.GetNumberOfPoints()); else Console.WriteLine("Not Pointy.."); |
명시적 인터페이스 구현
명시적 인터페이스 기법을 이용하면 객체 사용자가 이름 충돌을 피하면서, 정확한 인터페이스 참조자를 이용해서 해당 인터페이스에 정의된 메소드에만 접근할 수 있도록 할 수 있다.
public class Shape { public string petName; public Shape() { } public Shape(string name) { petName = name; } virtual public void Draw() { } }
public class Line : Shape, IDraw3D { void IDraw3D.Draw() { Console.WriteLine("Drawing a 3D line.."); }
public override void Draw() { Console.WriteLine("Drawing a line.."); } } public interface IDraw3D { void Draw(); } |
명시적 인터페이스를 구현 할 때는 접근 한정자를 사용할 수 없다.
예를 들어 보면 public void IDraw3D.Draw() 이다. 접근 한정자를 사용할 수 없는 이유는 명시적 인터페이스 메소드 구현을 사용하는 이유가 해당 인터페이스 메소드의 범위를 인터페이스 레벨로 제한하기 위한 것이기 때문이다. public 키워드를 추가한다는 것은 이 메소드를 해당 클래스의 public 멤버들 중 하나로 간주 하겠다는 뜻이된다.
인터페이스 계층 구조 만들기
클래스들 간에 기본 클래스와 파생 클래스의 관계를 만들 수 있는 것과 마찬가지로 인터페이스들 간에도 파생 관계를 만들 수 있다.
interface IDraw { void Draw(); } interface IDraw2 : IDraw { void dDrawToPrinter(); } interface IDraw3 : IDraw2 { void DrawToMataFile(); }
public class SuperImage : IDraw3 { void IDraw.Draw() { Console.WriteLine("Default Draw~"); } void IDraw2.dDrawToPrinter() { Console.WriteLine("Printer Draw~"); } void IDraw3.DrawToMataFile() { Console.WriteLine("MataFile Draw~"); } }
class SuperImageApp { static void Main(string[] args) { SuperImage si = new SuperImage(); IDraw itfDraw = (IDraw)si; itfDraw.Draw(); if (itfDraw is IDraw3) { IDraw3 itfDraw3 = (IDraw3)itfDraw; itfDraw3.DrawToMataFile(); itfDraw3.dDrawToPrinter(); } } } |
IDraw, IDraw2, IDraw3 인터페이스에서 IDraw를 상속받은 IDraw2를 IDraw3에서 상속을 받는다. 이렇게 인터페이스 간의 상속 관계가 계층 구조가 된다. si 인스턴스에서 명시적 형식 변환으로 인터페이스 참조를 얻어 최하위 IDraw3 인터페이스에서 전 계층의 함수를 호출 하여 사용하면 된다. |
|
.NET 기본 클래스 라이브러리에 미리 정의 되어있는 인터페이스
인터페이스 명 |
설명 |
IConvertible |
트정 언어에 종속되지 않은 표현을 이용해서 실행 중에 형식들 간의 형식을 변환 할 수 있다. |
IEnumerable |
지정된 형식의 컬렉션을 단순하게 반복할 수 있도록 지원하는 열거자를 노출한다. |
IEnumerator |
임의의 객체가 형식들의 내부 컬렉션을 순회하는데 이용할 수 있다. |
ICloneable |
호출자에게 자기 자신의 복사본을 반활할 수 있는 사용자 지정 형식을 만들 수 있다. |
IComparable |
내부 키에 기반해서 객체를 정렬하는데 이용할 수 있다. |
IComparer |
두 개체를 비교하는 메소드를 노출 한다. |
System.Collections 네임스페이스
System.Collections에 있는 인터페이스
인터페이스 명 |
설명 |
ICollection |
컬렉션 클래스의 일반적인 특징을 정의한다. |
IComparer |
두 객체를 비교하는데 이용된다. |
IDictionary |
객체가 내용을 이름/값 쌍을 이용해서 나타내는 데 이용된다. |
IDictionary Enumerator |
IDictionary를 지원하는 객체의 내용을 열거하는데 이용한다. |
IEnummerable |
주어진 객체를 위한 IEnumerator 인터페이스를 반환한다. |
IEnumerator |
Foreach 스타일의 반복 처리를 지원하기 위해 사용된다. |
IHashCodeProvider |
개인화된 해시 알고리즘을 이용해서 구현하는 형식에 대한 해시 코드를 반환한다. |
IList |
객체 리스트에서 항목을 추가하고 제거하고 색인을 작성하는 동작을 제공한다. |