interface 타입

interface 타입은 인터페이스라고 불리는 메서드 집합(method set)을 명시한다. 주어진 인터페이스의 확대집합(superset)에 해당하는 메서드 집합을 갖고 있는 어떠한 타입의 값이든 interface 타입의 변수에 저장할 수 있다. 그러한 타입에 대해서는 인터페이스를 구현했다라고 말한다. 초기화되지 않은 interface 타입의 변수는 nil 값을 갖는다.

InterfaceType      = "interface" "{" { MethodSpec ";" } "}" .
MethodSpec         = MethodName Signature | InterfaceTypeName .
MethodName         = identifier .
InterfaceTypeName  = TypeName .

모든 메서드 집합에서 그런 것 처럼, interface 타입내, 각 메서드는 blank 식별자(blank identifier)가 아닌 고유한 명칭을 가져야 한다.

// A simple File interface
interface {
    Read(b Buffer) bool
    Write(b Buffer) bool
    Close()
}

한 인터페이스는 여러 타입으로 구현될 수도 있다. 예를 들어, 만약 타입 S1S2가 다음과 같은 메서드 집합을 가지고 있다면

func (p T) Read(b Buffer) bool { return … }
func (p T) Write(b Buffer) bool { return … }
func (p T) Close() { … }

(위에서 TS1일 수도 있고 S2일 수도 있다) 이들이 가지고 있거나 공유하고 있는 다른 메서드들과는 상관없이 S1S2File 인터페이스를 구현한 것이다.

타입은 자신의 메서드에 인터페이스의 메서드를 포함시키는 방법을 통해 어떠한 인터페이스든지 구현할 수 있기 때문에 여러 인터페이스를 함께 구현하는 것도 가능하다. 예를 들어, 모든 타입은 empty interface를 구현하고 있다:

interface{}

추가로, Locker라는 인터페이스를 정의한 타입 선언문내 열거되어 있는 인터페이스 사양을 보자.

type Locker interface {
    Lock()
    Unlock()
}

만약 S1S2가 아래의 메서드도 구현했다면

func (p T) Lock() { … }
func (p T) Unlock() { … }

이들은 File 인터페이스 뿐만 아니라 Locker 인터페이스도 구현한 것이다.

인터페이스 T는 메서드의 사양이 있어야 할 자리에 (경우에 따라서는 패키지 이름을 동반한) interface 타입 이름 E를 사용할 수도 있다. 이것을 T안에 인터페이스 E임베딩했다고 부른다; 임베딩은 (엑스포트 여부에 상관없이) E의 모든 메서드를 인터페이스 T에 추가한다.

type ReadWriter interface {
    Read(b Buffer) bool
    Write(b Buffer) bool
}

type File interface {
    ReadWriter  // ReadWriter의 메서드를 추가한 것과 같음
    Locker      // Locker의 메서드를 추가한 것과 같음
    Close()
}

type LockedFile interface {
    Locker
    File        // 허용안됨: Lock, Unlock이 고유하지 않음
    Lock()      // 허용안됨: Lock이 고유하지 않음
}

인터페이스 T는 자신을 임베딩할 수 없고 T를 임베딩한 다른 어떤 인터페이스 타입도 재귀적으로 임베딩할 수 없다.

// 허용안됨: Bad는 자신을 임베딩할 수 없음
type Bad interface {
    Bad
}

// 허용안됨: Bad1은 Bad2를 이용해 임베딩할 수 없음
type Bad1 interface {
    Bad2
}
type Bad2 interface {
    Bad1
}

results matching ""

    No results matching ""