메서드 오버라이딩
임베디드 필드에 정의된 메서드를 오버라이딩(Overriding)할 수도 있다.
func (t DiscountItem) Cost() float64 { return t.Item.Cost() * (1.0 - t.discountRate/100) } func main() { shoes := Item{"Women's Walking Shoes", 30000, 2} eventShoes := DiscountItem{ Item{"Sports Shoes", 50000, 3}, 10.00, } fmt.Println(shoes.Cost()) // 60000 fmt.Println(eventShoes.Cost()) // 135000 fmt.Println(eventShoes.Item.Cost()) // 150000 }
Item 타입에 정의된 Cost() 메서드와 이름이 같은 메서드를 DiscountItem 타입에 추가했다. 이로써 Item의 Cost() 메서드는 오버라이딩되었다. DiscountItem의 Cost() 메서드에서 t.Item.Cost()로 Item의 Cost() 메서드를 사용한다. 물론 eventShoes.Item.Cost()처럼 Item의 Cost() 메서드를 직접 호출할 수도 있다.
Note 오버로딩(Overloading)
Go는 이름이 같은 메서드를 생성할 수 없다. 즉, 오버로딩(이름은 같지만 매개변수가 다른 메서드)을 지원하지 않는다. 매개변수가 다르면 메서드 이름도 다르게 지정해야 한다.
예를 들어 기본 라이브러리에 있는 strings.Reader 타입은 매개변수에 따라 다른 메서드 세 개를 제공한다.
func (r *Reader) Read(b []byte) (n int, err error) func (r *Reader) ReadByte() (b byte, err error) func (r *Reader) ReadRune() (ch rune, size int, err error)
메서드의 매개변수 타입 앞에 생략 부호(...)를 표기하여 가변 인자로 정의하면 오버로딩과 유사한 효과를 줄 수 있다.
func main() { shoes := Item{"Women's Walking Shoes", 30000, 2} eventShoes := DiscountItem{ Item{"Sports Shoes", 50000, 3}, 10.00, } display(shoes.name) display(shoes.name, eventShoes.name) } func display(values ...string) { for i := 0; i < len(values); i++ { fmt.Println(values[i]) } }