Menu
Coddy logo textTech

임베딩된 메서드 섀도잉

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 39번째.

때로는 외부 구조체가 임베디드 타입에 이미 있는 메서드를 자체적으로 구현해야 합니다. 이를 섀도잉이라고 하며, 승격된 메서드를 사용자 지정 동작으로 재정의할 수 있게 해줍니다.

임베드된 method와 같은 이름으로 외부 구조체에 method를 정의하면 외부 method가 우선합니다:

type Animal struct {
    Name string
}

func (a Animal) Speak() string {
    return "Some sound"
}

type Dog struct {
    Animal
    Breed string
}

func (d Dog) Speak() string {
    return "Woof!"
}

이제 Dog에서 Speak()을 호출하면 바깥쪽 메서드가 사용됩니다:

func main() {
    d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}
    
    fmt.Println(d.Speak())        // Woof! - Dog의 메서드
    fmt.Println(d.Animal.Speak()) // Some sound - Animal의 메서드
}

embedded method는 사라진 것이 아닙니다. embedded type 이름을 통해 여전히 명시적으로 액세스할 수 있습니다. 이 패턴은 원래 구현을 사용할 수 있는 상태로 동작을 사용자 지정하고 싶을 때 유용합니다. 예를 들어 overriding method 내부에서 이를 호출할 수 있습니다.

func (d Dog) Speak() string {
    return d.Animal.Speak() + " (but actually Woof!)"
}

섀도잉을 사용하면 명시적 한정자를 통해 원래 동작에 계속 접근하면서 어떤 동작을 노출할지 제어할 수 있습니다.

challenge icon

챌린지

쉬움

서로 다른 notification channel이 메시지의 형식 지정 및 전달 방식을 사용자 지정할 수 있는 notification system을 만들어 보겠습니다. method shadowing을 사용하여 특정 channel이 기본 동작을 재정의하면서도 필요할 때 원래 구현에 액세스할 수 있도록 합니다.

코드를 세 개의 파일로 구성합니다:

  • base.go: TitlePriority fields(둘 다 문자열)를 포함하는 BaseNotification 구조체를 Create합니다. notification을 표준 형식인 [Priority] Title로 반환하는 Format() string method를 추가합니다.
  • channels.go: BaseNotification을 embed하고 Format method를 자체 구현으로 shadow하는 두 가지 notification channel type을 Create합니다:
    • EmailNotification에는 Recipient field가 있습니다. 해당 Format()Email to [Recipient]: [Priority] Title을 반환해야 합니다.
    • SlackNotification에는 Channel field가 있습니다. 해당 Format()은 embed된 BaseNotification.Format() method를 call하고 결과 앞에 #[Channel]: 을 prepend해야 합니다.
  • main.go: 입력에서 notification 세부 정보를 Read하고, 두 type의 notification을 Create한 다음 다음을 출력하여 shadowing을 보여 줍니다:
    1. EmailNotification의 형식 지정된 output (해당 shadow된 method 사용)
    2. EmailNotification의 base format (embed된 method를 explicitly call)
    3. SlackNotification의 형식 지정된 output (내부적으로 base method 사용)

다음 입력이 제공됩니다:

  • 1번째 줄: notification title
  • 2번째 줄: Priority level
  • 3번째 줄: Email recipient
  • 4번째 줄: Slack channel name

예를 들어 Server Alert, HIGH, admin@company.com, ops-alerts가 주어지면 output은 다음과 같아야 합니다:

Email to admin@company.com: HIGH Server Alert
[HIGH] Server Alert
#ops-alerts: [HIGH] Server Alert

EmailNotification은 base formatting을 완전히 대체하는 반면, SlackNotification은 원래 method를 call하고 channel context를 추가하여 이를 향상한다는 점에 유의하세요. 두 접근 방식은 method shadowing을 효과적으로 사용하는 서로 다른 방법을 보여 줍니다.

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// 알림 제목 읽기
	scanner.Scan()
	title := scanner.Text()
	
	// 우선순위 수준 읽기
	scanner.Scan()
	priority := scanner.Text()
	
	// 이메일 수신자 읽기
	scanner.Scan()
	recipient := scanner.Text()
	
	// Slack 채널 이름 읽기
	scanner.Scan()
	channel := scanner.Text()
	
	// TODO: 기본 알림, title, priority, recipient로 EmailNotification 생성
	
	// TODO: 기본 알림, title, priority, channel로 SlackNotification 생성
	
	// TODO: EmailNotification의 형식화된 출력 출력 (shadowed method 사용)
	
	// TODO: EmailNotification의 기본 형식 출력 (embedded method를 명시적으로 호출)
	
	// TODO: SlackNotification의 형식화된 출력 출력
	
	fmt.Println() // 플레이스홀더 - 구현 시 제거
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Go 컴파일러