diff --git a/interfaces/08-composition/book.go b/interfaces/08-composition/book.go index 4d1e5ac..c583442 100644 --- a/interfaces/08-composition/book.go +++ b/interfaces/08-composition/book.go @@ -7,19 +7,35 @@ package main -import "fmt" +import ( + "fmt" + "strconv" + "time" +) type book struct { - title string - price money - readTime int + *product + published interface{} } -func (b book) print() { - fmt.Printf("%-15s: %s\n", b.title, b.price.string()) +func (b *book) String() string { + p := format(b.published) + return fmt.Sprintf("%s - (%v)", b.product, p) } -// TODO: NEW -func (b book) sum() money { - return b.price +func format(v interface{}) string { + var t int + + switch v := v.(type) { + case int: + t = v + case string: + t, _ = strconv.Atoi(v) + default: + return "unknown" + } + + const layout = "2006/01" + u := time.Unix(int64(t), 0) + return u.Format(layout) } diff --git a/interfaces/08-composition/discount.go b/interfaces/08-composition/discount.go deleted file mode 100644 index 592c545..0000000 --- a/interfaces/08-composition/discount.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -// usually: include the discount method in the list.go -// it is here for clarity - -// TODO: NEW -func (l list) discount(ratio float64) { - type discounter interface { - discount(float64) - } - - for _, it := range l { - if it, ok := it.(discounter); ok { - it.discount(ratio) - } - } -} diff --git a/interfaces/08-composition/game.go b/interfaces/08-composition/game.go index 47ba4e6..6811170 100644 --- a/interfaces/08-composition/game.go +++ b/interfaces/08-composition/game.go @@ -7,27 +7,6 @@ package main -import "fmt" - type game struct { - title string - price money - playTime int -} - -func (g *game) print() { - fmt.Printf("%-15s: %s\n", g.title, g.price.string()) -} - -// func (g *game) String() string { -// return fmt.Sprintf("%-15s: $%.2f", g.title, g.price) -// } - -func (g *game) discount(ratio float64) { - g.price *= money(1 - ratio) -} - -// TODO: NEW -func (g *game) sum() money { - return g.price + *product } diff --git a/interfaces/08-composition/list.go b/interfaces/08-composition/list.go index 4bbf89d..bd87c8c 100644 --- a/interfaces/08-composition/list.go +++ b/interfaces/08-composition/list.go @@ -7,28 +7,51 @@ package main -import "fmt" +import ( + "fmt" + "strings" +) + +type summer interface { + sum() money +} + +type item interface { + summer // same as: `sum() money` + fmt.Stringer // same as: `String() string` +} type list []item -func (l list) print() { +func (l list) String() string { if len(l) == 0 { - fmt.Println("Sorry. Our store is closed. We're waiting for the delivery 🚚.") - return + return "Sorry. We're waiting for delivery 🚚." + } + + var str strings.Builder + for _, it := range l { + fmt.Fprintf(&str, "%s\n", it) + } + fmt.Fprintf(&str, "\tTOTAL : $%.2f", l.sum()) + + return str.String() +} + +func (l list) sum() (total money) { + for _, it := range l { + total += it.sum() + } + return +} + +func (l list) discount(ratio float64) { + type discounter interface { + discount(float64) } for _, it := range l { - it.print() + if it, ok := it.(discounter); ok { + it.discount(ratio) + } } - - // TODO: NEW - fmt.Printf("\tTOTAL : $%.2f\n", l.sum()) -} - -// TODO: NEW -func (l list) sum() (n money) { - for _, it := range l { - n += it.sum() - } - return n } diff --git a/interfaces/08-composition/main.go b/interfaces/08-composition/main.go index 74d29f2..606bc06 100644 --- a/interfaces/08-composition/main.go +++ b/interfaces/08-composition/main.go @@ -7,37 +7,36 @@ package main -// import "fmt" +import ( + "fmt" + "sort" +) func main() { - var ( - mobydick = book{title: "moby dick", price: 10, readTime: 10} - minecraft = game{title: "minecraft", price: 20, playTime: 5} - tetris = game{title: "tetris", price: 5, playTime: 2} - rubik = puzzle{title: "rubik's cube", price: 5} - ) + store := list{ + &book{&product{"moby dick", 10}, 118281600}, + &book{&product{"odyssey", 15}, "733622400"}, + &book{&product{"hobbit", 25}, nil}, + &puzzle{&product{"rubik's cube", 5}}, + &game{&product{"minecraft", 20}}, + &game{&product{"tetris", 5}}, + &toy{&product{"yoda", 150}}, + } - var store list - store = append(store, &minecraft, &tetris, mobydick, rubik) - // tetris.discount(.8) - // store.print() + books := store[:3] + others := store[3:] - store.discount(.5) - store.print() + books.discount(.5) + fmt.Printf("%s\n", store) - // t := store.time() - // fmt.Printf("Total entertainment time: %d hours\n", t) + sort.Sort(byPrice(others)) + fmt.Printf("\n%s\n", store) - // games := store[:2] - // other := store[2:] - // games.print() - // other.print() - // list{games, other}.print() + store = list{books, others} + fmt.Printf("\n%s\n", store) - // var b *book - - // var np printer - // np = b - // // p := printer(puzzle{title: "sidewinder", price: 10}) - // fmt.Println(np == nil) + // store.discount(.5) + // // sort.Sort(sort.Reverse(byPrice(store))) + // sort.Sort(byName(store)) + // fmt.Println(store) } diff --git a/interfaces/08-composition/money.go b/interfaces/08-composition/money.go index 86f7d63..095a039 100644 --- a/interfaces/08-composition/money.go +++ b/interfaces/08-composition/money.go @@ -11,6 +11,6 @@ import "fmt" type money float64 -func (m money) string() string { +func (m money) String() string { return fmt.Sprintf("$%.2f", m) } diff --git a/interfaces/08-composition/product.go b/interfaces/08-composition/product.go new file mode 100644 index 0000000..f1b3383 --- /dev/null +++ b/interfaces/08-composition/product.go @@ -0,0 +1,27 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +import "fmt" + +type product struct { + title string + price money +} + +func (p *product) discount(ratio float64) { + p.price *= money(1 - ratio) +} + +func (p *product) sum() money { + return p.price +} + +func (p *product) String() string { + return fmt.Sprintf("%-15s: %s", p.title, p.price) +} diff --git a/interfaces/08-composition/puzzle.go b/interfaces/08-composition/puzzle.go index 52dd4c1..bf3ecc4 100644 --- a/interfaces/08-composition/puzzle.go +++ b/interfaces/08-composition/puzzle.go @@ -7,18 +7,6 @@ package main -import "fmt" - type puzzle struct { - title string - price money -} - -func (p puzzle) print() { - fmt.Printf("%-15s: %s\n", p.title, p.price.string()) -} - -// TODO: NEW -func (p puzzle) sum() money { - return p.price + *product } diff --git a/interfaces/08-composition/sort.go b/interfaces/08-composition/sort.go new file mode 100644 index 0000000..58d358c --- /dev/null +++ b/interfaces/08-composition/sort.go @@ -0,0 +1,20 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +type byPrice list + +func (l byPrice) Less(i, j int) bool { return l[i].sum() < l[j].sum() } +func (l byPrice) Len() int { return len(l) } +func (l byPrice) Swap(i, j int) { l[i], l[j] = l[j], l[i] } + +type byName list + +func (l byName) Less(i, j int) bool { return l[i].String() < l[j].String() } +func (l byName) Len() int { return len(l) } +func (l byName) Swap(i, j int) { l[i], l[j] = l[j], l[i] } diff --git a/interfaces/08-composition/time.go b/interfaces/08-composition/time.go deleted file mode 100644 index ef7ff17..0000000 --- a/interfaces/08-composition/time.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -// usually: include the time method in the list.go -// it is here for clarity - -// TODO: NEW -// you could include a time method in the book and game instead. -// but sometimes it is not possible to do so. -func (l list) time() (total int) { - for _, it := range l { - switch it := it.(type) { - case *game: - total += it.playTime - case book: - total += it.readTime - } - } - return total -} diff --git a/interfaces/08-composition/toy.go b/interfaces/08-composition/toy.go new file mode 100644 index 0000000..73e99c4 --- /dev/null +++ b/interfaces/08-composition/toy.go @@ -0,0 +1,12 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +type toy struct { + *product +} diff --git a/interfaces/08-composition/types.go b/interfaces/08-composition/types.go deleted file mode 100644 index 8a10e3a..0000000 --- a/interfaces/08-composition/types.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -// don't separate your interfaces like this. -// put them in the same file where you need to use them. -// this is here for clarity - -type printer interface { - print() -} - -// TODO: NEW -type summer interface { - sum() money -} - -// TODO: NEW -// interface embedding -// When an interface includes multiple methods, -// choose a name that accurately describes its purpose. -type item interface { - printer - summer -}