๊ธฐ๋ณธ ๊ฐ๋
์๋ฒ ๋ฉ์ Go์์ ์์๊ณผ ๋น์ทํ ํจ๊ณผ๋ฅผ ๋ด๋ ๋ฐฉ๋ฒ. ํ์ง๋ง ์์์ด ์๋๋ผ ์ปดํฌ์ง์ (composition).
๊ตฌ์กฐ์ฒด ์๋ฒ ๋ฉ
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
type Person struct {
Name string
Age int
}
func (p Person) Greet() string {
return "์๋
, ๋๋ " + p.Name
}
type Employee struct {
Person // ์๋ฒ ๋ฉ! ํ์
๋ง ์ฐ๊ณ ํ๋๋ช
์์
Position string
Salary int
}
func main() {
emp := Employee{
Person: Person{Name: "๊น์ฒ ์", Age: 30},
Position: "๊ฐ๋ฐ์",
Salary: 5000,
}
// Person์ ํ๋์ ์ง์ ์ ๊ทผ ๊ฐ๋ฅ
fmt.Println(emp.Name) // "๊น์ฒ ์"
fmt.Println(emp.Age) // 30
// Person์ ๋ฉ์๋๋ ์ง์ ํธ์ถ ๊ฐ๋ฅ
fmt.Println(emp.Greet()) // "์๋
, ๋๋ ๊น์ฒ ์"
// ๋ฌผ๋ก ๋ช
์์ ์ ๊ทผ๋ ๊ฐ๋ฅ
fmt.Println(emp.Person.Name) // "๊น์ฒ ์"
fmt.Println(emp.Person.Greet()) // "์๋
, ๋๋ ๊น์ฒ ์"
}
๋ฉ์๋ ์น๊ฒฉ(Method Promotion)
type Animal struct {
Name string
}
func (a Animal) Speak() string {
return a.Name + "๊ฐ ์๋ฆฌ๋"
}
func (a Animal) Move() string {
return a.Name + "๊ฐ ์์ง์"
}
type Dog struct {
Animal
Breed string
}
// Dog ํ์
์ ์๋ก์ด ๋ฉ์๋ ์ถ๊ฐ
func (d Dog) Bark() string {
return d.Name + "๊ฐ ๋ฉ๋ฉ!"
}
// Animal์ ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋
func (d Dog) Speak() string {
return d.Name + "๊ฐ ๋ฉ๋ฉ ์ง์"
}
func main() {
dog := Dog{
Animal: Animal{Name: "๋ฐ๋์ด"},
Breed: "์ง๋๊ฐ",
}
fmt.Println(dog.Move()) // "๋ฐ๋์ด๊ฐ ์์ง์" (Animal์์ ์น๊ฒฉ)
fmt.Println(dog.Speak()) // "๋ฐ๋์ด๊ฐ ๋ฉ๋ฉ ์ง์" (Dog์์ ์ค๋ฒ๋ผ์ด๋)
fmt.Println(dog.Bark()) // "๋ฐ๋์ด๊ฐ ๋ฉ๋ฉ!" (Dog ๊ณ ์ ๋ฉ์๋)
}
๋ค์ค ์๋ฒ ๋ฉ
type Reader struct{}
func (r Reader) Read() string { return "์ฝ๊ธฐ" }
type Writer struct{}
func (w Writer) Write() string { return "์ฐ๊ธฐ" }
type ReadWriter struct {
Reader
Writer
}
func main() {
rw := ReadWriter{}
fmt.Println(rw.Read()) // "์ฝ๊ธฐ"
fmt.Println(rw.Write()) // "์ฐ๊ธฐ"
}
์ด๋ฆ ์ถฉ๋ ์ ํด๊ฒฐ
type A struct{}
func (a A) Method() string { return "A" }
type B struct{}
func (b B) Method() string { return "B" }
type C struct {
A
B
}
func main() {
c := C{}
// ์ด๊ฑด ์๋ฌ! ์ด๋ค Method()์ธ์ง ๋ชจํธํจ
// fmt.Println(c.Method())
// ๋ช
์์ ์ผ๋ก ์ ๊ทผํด์ผ ํจ
fmt.Println(c.A.Method()) // "A"
fmt.Println(c.B.Method()) // "B"
}
์ธํฐํ์ด์ค ์๋ฒ ๋ฉ
type Reader interface {
Read() error
}
type Writer interface {
Write() error
}
type ReadWriter interface {
Reader // ์ธํฐํ์ด์ค๋ ์๋ฒ ๋ฉ ๊ฐ๋ฅ
Writer
}
// ์๋ ์๋์ ๋์ผ
type ReadWriter2 interface {
Read() error
Write() error
}
1. ๊ณตํต ๊ธฐ๋ฅ ์ถ๊ฐ
type Timestamp struct {
CreatedAt time.Time
UpdatedAt time.Time
}
func (t *Timestamp) Touch() {
now := time.Now()
if t.CreatedAt.IsZero() {
t.CreatedAt = now
}
t.UpdatedAt = now
}
type User struct {
Timestamp // ๋ชจ๋ ์ํฐํฐ์ ๊ณตํต์ผ๋ก ์ถ๊ฐ
Name string
Email string
}
type Post struct {
Timestamp
Title string
Content string
}
func main() {
user := &User{Name: "๊น์ฒ ์", Email: "kim@example.com"}
user.Touch() // Timestamp์ ๋ฉ์๋ ์ฌ์ฉ
post := &Post{Title: "์ ๋ชฉ", Content: "๋ด์ฉ"}
post.Touch() // ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ์ฉ ๊ฐ๋ฅ
}
2. ๊ธฐ์กด ํ์ ํ์ฅ
type MyString string
func (ms MyString) IsPalindrome() bool {
s := string(ms)
runes := []rune(s)
for i := 0; i < len(runes)/2; i++ {
if runes[i] != runes[len(runes)-1-i] {
return false
}
}
return true
}
type EnhancedString struct {
MyString
}
func (es EnhancedString) Length() int {
return len(string(es.MyString))
}
func main() {
enhanced := EnhancedString{MyString: "level"}
fmt.Println(enhanced.IsPalindrome()) // true
fmt.Println(enhanced.Length()) // 5
}
์๋ฒ ๋ฉ vs ์์ ์ฐจ์ด์
์์ (๋ค๋ฅธ ์ธ์ด)
- IS-A ๊ด๊ณ: Dog๋ Animal์ด๋ค
- ๋ฐํ์ ๋คํ์ฑ ์ง์
์๋ฒ ๋ฉ (Go)
- HAS-A ๊ด๊ณ: Employee๋ Person์ ๊ฐ์ง๋ค
- ์ปดํ์ผ ํ์์ ๊ฒฐ์ ๋จ
- ๋ ๋ช ์์ ์ด๊ณ ์์ธก ๊ฐ๋ฅ
func processAnimal(a Animal) {
fmt.Println(a.Speak())
}
func main() {
dog := Dog{Animal: Animal{Name: "๋ฐ๋์ด"}}
// ์ด๊ฑด ์ ๋จ! Dog๋ Animal์ด ์๋๋ผ Animal์ ๊ฐ์ง๋ ๊ฒ
// processAnimal(dog)
// ๋ช
์์ ์ผ๋ก Animal ๋ถ๋ถ์ ์ ๋ฌํด์ผ ํจ
processAnimal(dog.Animal)
}
์ฅ์ ๊ณผ ๋จ์
์ฅ์
- ์ฝ๋ ์ฌ์ฌ์ฉ: ๊ณตํต ๊ธฐ๋ฅ์ ์ฝ๊ฒ ๊ณต์
- ๋จ์ํจ: ๋ณต์กํ ์์ ๊ณ์ธต ์์
- ๋ช ์์ : ์ด๋ค ๊ธฐ๋ฅ์ด ์ด๋์ ์ค๋์ง ๋ช ํ
๋จ์
- ๋คํ์ฑ ์ ํ: ๋ฐํ์ ๋คํ์ฑ ์ด๋ ค์
- ์ธํฐํ์ด์ค ๋ถ๋ฆฌ: ๊ฐ๊ฐ ๋ค๋ฅธ ์ธํฐํ์ด์ค๋ก ์ฒ๋ฆฌํด์ผ ํจ