인터페이스
인터페이스 (Interfaces)
클래스가 특정 계약(contract)을 충족하도록 강제하는 D의 인터페이스 기능을 다룹니다. 인터페이스의 기본 규칙, 메서드 구현, 재구현, 메서드 계약, 그리고 COM·C++ 인터페이스처럼 특수한 변형까지 정리했어요.
본문
인터페이스에서 상속받은 클래스는 그 인터페이스 타입으로 암시적으로 변환될 수 있습니다.
인터페이스는 클래스에서 파생될 수 없고 오직 다른 인터페이스에서만 파생됩니다. 인터페이스 인스턴스는 상속된 어떤 인터페이스로든 암시적으로 변환됩니다. 클래스는 인터페이스를 여러 번 파생할 수 없습니다.
interface I
{
void foo();
}
class A : I, I // error, duplicate interface
{
}
인터페이스의 인스턴스는 직접 생성할 수 없습니다:
interface I
{
void foo();
}
...
I iface = new I(); // error, cannot create instance of interface
인터페이스 인스턴스는 Object로 캐스트하거나, 다른 클래스 타입으로 동적 캐스트할 수 있습니다.
인터페이스 메서드 본문 (Interface Method Bodies)
가상(virtual) 인터페이스 멤버 함수는 구현을 갖지 않습니다. 인터페이스는 static이나 final 함수를 구현할 수 있어요.
interface I
{
void bar() { } // error, implementation not allowed
static void foo() { } // ok
final void abc() { } // ok
}
인터페이스는 멤버에 함수 템플릿을 가질 수 있습니다. 인스턴스화된 모든 함수는 암시적으로 final입니다.
interface I
{
void foo(T)() { } // ok, it's implicitly final
}
인터페이스에서 상속받은 클래스는 final이거나 static인 인터페이스 멤버 함수를 오버라이드할 수 없습니다.
interface I
{
void bar();
static void foo() { }
final void abc() { }
}
class C : I
{
void bar() { } // ok
void foo() { } // error, cannot override static I.foo()
void abc() { } // error, cannot override final I.abc()
}
인터페이스 구현 (Implementing Interfaces)
인터페이스에서 상속받은 클래스에서 모든 가상 인터페이스 함수를 정의해야 합니다:
interface I
{
void foo();
}
class A : I
{
void foo() { } // ok, provides implementation
}
class B : I
{
int foo() { } // error, no `void foo()` implementation
}
인터페이스는 기반 클래스에서 상속될 수 있고, 인터페이스 함수도 오버라이드될 수 있습니다:
interface I
{
int foo();
}
class A : I
{
int foo() { return 1; }
}
class B : A
{
override int foo() { return 2; }
}
B b = new B();
assert(b.foo() == 2);
I i = b; // ok since B inherits A's I implementation
assert(i.foo() == 2);
인터페이스 재구현 (Reimplementing Interfaces)
인터페이스는 파생 클래스에서 재구현될 수 있습니다:
interface I
{
int foo();
}
class A : I
{
int foo() { return 1; }
}
class B : A, I // reimplement I
{
override int foo() { return 2; }
}
B b = new B();
assert(b.foo() == 2);
I i = b;
assert(i.foo() == 2);
A a = b;
I i2 = a;
assert(i2.foo() == 2); // i2 has A's virtual pointer for foo which points to B.foo
재구현된 인터페이스는 모든 인터페이스 함수를 구현해야 하며, 슈퍼클래스에서 상속받지 않습니다:
interface I
{
int foo();
}
class A : I
{
int foo() { return 1; }
}
class B : A, I
{
} // error, no foo() for interface I
인터페이스 메서드 계약 (Interface Method Contracts)
인터페이스 멤버 함수는 함수 본문이 없어도 계약(contract)을 가질 수 있습니다. 계약은 그 인터페이스 멤버 함수를 구현하는 어떤 클래스 멤버 함수에도 상속됩니다.
interface I
{
int foo(int i)
in { assert(i > 7); }
out (result) { assert(result & 1); }
void bar();
}
const와 immutable 인터페이스 (Const and Immutable Interfaces)
인터페이스가 const나 immutable 저장 클래스를 가지면, 인터페이스의 모든 멤버가 const 또는 immutable입니다. 이 저장 클래스는 상속되지 않습니다.
COM 인터페이스 (COM Interfaces)
인터페이스의 변형으로 COM 인터페이스가 있습니다. COM 인터페이스는 Windows COM 객체에 직접 매핑되도록 설계되었어요. 어떤 COM 객체든 COM 인터페이스로 표현할 수 있고, COM 인터페이스를 가진 어떤 D 객체든 외부 COM 클라이언트가 사용할 수 있습니다.
COM 인터페이스는 인터페이스 core.sys.windows.com.IUnknown에서 파생된 것으로 정의됩니다. COM 인터페이스는 일반 D 인터페이스와 다음 점에서 다릅니다:
- 인터페이스
core.sys.windows.com.IUnknown에서 파생된다. destroy의 인자가 될 수 없다.- 참조를 둘러싼 클래스 객체로 업캐스트할 수 없고, 파생 인터페이스로 다운캐스트할 수도 없다.
- 다른 COM 인터페이스로 변환하려면 표준 COM 방식으로 그 인터페이스에 대한
QueryInterface()를 구현한다. - COM 인터페이스에서 파생된 클래스는 COM 클래스입니다.
- COM 클래스 멤버 함수의 기본 링키지는
extern(System)입니다.
참고: D 인터페이스나 클래스(
IUnknown에서 상속받지 않는 것들)의 기반 클래스 메서드를 구현하거나 오버라이드할 때는 명시적으로extern(D)링키지를 표시하세요.
import core.sys.windows.windows;
import core.sys.windows.com;
interface IText
{
void write();
}
abstract class Printer : IText
{
void print() { }
}
class C : Printer, IUnknown
{
// Implements the IText `write` class method.
extern(D) void write() { }
// Overrides the Printer `print` class method.
extern(D) override void print() { }
// Overrides the Object base class `toString` method.
extern(D) override string toString() { return "Class C"; }
// Methods of class implementing the IUnknown interface have
// the extern(System) calling convention by default.
HRESULT QueryInterface(const(IID)*, void**);
uint AddRef();
uint Release();
}
이는 opCmp, toHash 등 다른 Object 메서드에도 동일하게 적용됩니다.
COM vtbl[]의 첫 번째 멤버는 InterfaceInfo에 대한 포인터가 아니라 첫 번째 가상 함수 포인터입니다.
참고: Modern COM Programming in D 문서도 참고하세요.
C++ 인터페이스 (C++ Interfaces)
C++ 인터페이스는 C++ 링키지로 선언된 인터페이스입니다:
extern (C++) interface Ifoo
{
void foo();
void bar();
}
이는 다음 C++ 선언에 대응하도록 의도된 것입니다:
class Ifoo
{
virtual void foo();
virtual void bar();
};
C++ 인터페이스에서 파생된 어떤 인터페이스도 C++ 인터페이스입니다. C++ 인터페이스는 D 인터페이스와 다음 점에서 다릅니다:
destroy의 인자가 될 수 없다.- 참조를 둘러싼 클래스 객체로 업캐스트할 수 없고, 파생 인터페이스로 다운캐스트할 수도 없다.
- 멤버 함수의 기본 호출 규약이 D 호출 규약이 아니라 C++ 호출 규약이다.
vtbl[]의 첫 번째 멤버가Interface에 대한 포인터가 아니라 첫 번째 가상 함수 포인터이다.