From 6b95995c816b6ca26e9ed546a2bc2d7d51e498d4 Mon Sep 17 00:00:00 2001 From: Inanc Gumus Date: Tue, 20 Aug 2019 19:03:57 +0300 Subject: [PATCH] add: interfaces assertion and composition (wip) --- interfaces/03-interfaces/main.go | 4 -- interfaces/04-assertion/book.go | 20 +++++++ interfaces/04-assertion/game.go | 24 ++++++++ interfaces/04-assertion/list.go | 84 +++++++++++++++++++++++++++ interfaces/04-assertion/main.go | 28 +++++++++ interfaces/04-assertion/puzzle.go | 23 ++++++++ interfaces/05-composition/book.go | 25 ++++++++ interfaces/05-composition/discount.go | 17 ++++++ interfaces/05-composition/game.go | 33 +++++++++++ interfaces/05-composition/list.go | 34 +++++++++++ interfaces/05-composition/main.go | 43 ++++++++++++++ interfaces/05-composition/puzzle.go | 24 ++++++++ interfaces/05-composition/time.go | 19 ++++++ interfaces/05-composition/types.go | 23 ++++++++ 14 files changed, 397 insertions(+), 4 deletions(-) create mode 100644 interfaces/04-assertion/book.go create mode 100644 interfaces/04-assertion/game.go create mode 100644 interfaces/04-assertion/list.go create mode 100644 interfaces/04-assertion/main.go create mode 100644 interfaces/04-assertion/puzzle.go create mode 100644 interfaces/05-composition/book.go create mode 100644 interfaces/05-composition/discount.go create mode 100644 interfaces/05-composition/game.go create mode 100644 interfaces/05-composition/list.go create mode 100644 interfaces/05-composition/main.go create mode 100644 interfaces/05-composition/puzzle.go create mode 100644 interfaces/05-composition/time.go create mode 100644 interfaces/05-composition/types.go diff --git a/interfaces/03-interfaces/main.go b/interfaces/03-interfaces/main.go index 2ba16b7..8e6b29d 100644 --- a/interfaces/03-interfaces/main.go +++ b/interfaces/03-interfaces/main.go @@ -22,10 +22,6 @@ func main() { // printer(tetris).discount(.8) store.print() - // type printer interface { - // print() - // } - // p can store a value of any type that has a `print()` method var p printer p = puzzle{title: "sidewinder", price: 10} diff --git a/interfaces/04-assertion/book.go b/interfaces/04-assertion/book.go new file mode 100644 index 0000000..c7c114b --- /dev/null +++ b/interfaces/04-assertion/book.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 + +import "fmt" + +type book struct { + title string + price float64 + readTime int +} + +func (b book) print() { + fmt.Printf("%-15s: $%.2f \n", b.title, b.price) +} \ No newline at end of file diff --git a/interfaces/04-assertion/game.go b/interfaces/04-assertion/game.go new file mode 100644 index 0000000..7503066 --- /dev/null +++ b/interfaces/04-assertion/game.go @@ -0,0 +1,24 @@ +// 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 game struct { + title string + price float64 + playTime int +} + +func (g *game) print() { + fmt.Printf("%-15s: $%.2f\n", g.title, g.price) +} + +func (g *game) discount(ratio float64) { + g.price *= (1 - ratio) +} \ No newline at end of file diff --git a/interfaces/04-assertion/list.go b/interfaces/04-assertion/list.go new file mode 100644 index 0000000..8a3cbf7 --- /dev/null +++ b/interfaces/04-assertion/list.go @@ -0,0 +1,84 @@ +// 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 printer interface { + print() +} + +type list []printer + +func (l list) print() { + if len(l) == 0 { + fmt.Println("Sorry. Our store is closed. We're waiting for the delivery 🚚.") + return + } + + for _, it := range l { + it.print() + } +} + +func (l list) discount(ratio float64) { + type discounter interface { + discount(float64) + } + + for _, it := range l { + if it, ok := it.(discounter); ok { + it.discount(ratio) + } + } +} + +// +// type assertion can pull out the real value behind an interface value. +// +// it can also check whether the value convertable to a given type. +// +// func (l list) discount(ratio float64) { +// for _, it := range l { +// // remember: interface is a type +// if it, ok := it.(interface{ discount(float64) }); ok { +// it.discount(ratio) +// } +// } +// } + +// +// type switch can pull out the real value behind an interface value. +// +// func (l list) discount(ratio float64) { +// for _, it := range l { +// switch it := it.(type) { +// case *game: +// it.discount(ratio) +// case *puzzle: +// it.discount(ratio) +// } +// } +// } + +// +// type switch can find the type behind an interface value. +// +// func (l list) discount(ratio float64) { +// for _, it := range l { +// switch it.(type) { +// case *game: +// fmt.Print("it's a *game! --> ") +// case *puzzle: +// fmt.Print("it's a *puzzle! --> ") +// default: +// fmt.Print("neither --> ") +// } +// it.print() +// } +// } diff --git a/interfaces/04-assertion/main.go b/interfaces/04-assertion/main.go new file mode 100644 index 0000000..bde7e9c --- /dev/null +++ b/interfaces/04-assertion/main.go @@ -0,0 +1,28 @@ +// 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 + +func main() { + var ( + mobydick = book{title: "moby dick", price: 10} + minecraft = game{title: "minecraft", price: 20} + tetris = game{title: "tetris", price: 5} + rubik = puzzle{title: "rubik's cube", price: 5} + ) + + var store list + store = append(store, &minecraft, &tetris, mobydick, &rubik) + + store.discount(.5) + store.print() + + // minecraft.discount(.5) + // minecraft.print() +} + +// store.discount() diff --git a/interfaces/04-assertion/puzzle.go b/interfaces/04-assertion/puzzle.go new file mode 100644 index 0000000..6776092 --- /dev/null +++ b/interfaces/04-assertion/puzzle.go @@ -0,0 +1,23 @@ +// 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 puzzle struct { + title string + price float64 +} + +func (p *puzzle) print() { + fmt.Printf("%-15s: $%.2f \n", p.title, p.price) +} + +func (p *puzzle) discount(ratio float64) { + p.price *= (1 - ratio) +} diff --git a/interfaces/05-composition/book.go b/interfaces/05-composition/book.go new file mode 100644 index 0000000..9fec6eb --- /dev/null +++ b/interfaces/05-composition/book.go @@ -0,0 +1,25 @@ +// 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 book struct { + title string + price float64 + readTime int +} + +func (b book) print() { + fmt.Printf("%-15s: $%.2f \n", b.title, b.price) +} + +// TODO: NEW +func (b book) sum() float64 { + return b.price +} diff --git a/interfaces/05-composition/discount.go b/interfaces/05-composition/discount.go new file mode 100644 index 0000000..592c545 --- /dev/null +++ b/interfaces/05-composition/discount.go @@ -0,0 +1,17 @@ +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/05-composition/game.go b/interfaces/05-composition/game.go new file mode 100644 index 0000000..0ff457e --- /dev/null +++ b/interfaces/05-composition/game.go @@ -0,0 +1,33 @@ +// 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 game struct { + title string + price float64 + playTime int +} + +func (g *game) print() { + fmt.Printf("%-15s: $%.2f\n", g.title, g.price) +} + +// func (g *game) String() string { +// return fmt.Sprintf("%-15s: $%.2f", g.title, g.price) +// } + +func (g *game) discount(ratio float64) { + g.price *= (1 - ratio) +} + +// TODO: NEW +func (g *game) sum() float64 { + return g.price +} diff --git a/interfaces/05-composition/list.go b/interfaces/05-composition/list.go new file mode 100644 index 0000000..cd34e48 --- /dev/null +++ b/interfaces/05-composition/list.go @@ -0,0 +1,34 @@ +// 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 list []item + +func (l list) print() { + if len(l) == 0 { + fmt.Println("Sorry. Our store is closed. We're waiting for the delivery 🚚.") + return + } + + for _, it := range l { + it.print() + } + + // TODO: NEW + fmt.Printf("\tTOTAL : $%.2f\n", l.sum()) +} + +// TODO: NEW +func (l list) sum() (n float64) { + for _, it := range l { + n += it.sum() + } + return n +} diff --git a/interfaces/05-composition/main.go b/interfaces/05-composition/main.go new file mode 100644 index 0000000..74d29f2 --- /dev/null +++ b/interfaces/05-composition/main.go @@ -0,0 +1,43 @@ +// 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" + +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} + ) + + var store list + store = append(store, &minecraft, &tetris, mobydick, rubik) + // tetris.discount(.8) + // store.print() + + store.discount(.5) + store.print() + + // t := store.time() + // fmt.Printf("Total entertainment time: %d hours\n", t) + + // games := store[:2] + // other := store[2:] + // games.print() + // other.print() + // list{games, other}.print() + + // var b *book + + // var np printer + // np = b + // // p := printer(puzzle{title: "sidewinder", price: 10}) + // fmt.Println(np == nil) +} diff --git a/interfaces/05-composition/puzzle.go b/interfaces/05-composition/puzzle.go new file mode 100644 index 0000000..cd3e133 --- /dev/null +++ b/interfaces/05-composition/puzzle.go @@ -0,0 +1,24 @@ +// 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 puzzle struct { + title string + price float64 +} + +func (p puzzle) print() { + fmt.Printf("%-15s: $%.2f \n", p.title, p.price) +} + +// TODO: NEW +func (p puzzle) sum() float64 { + return p.price +} diff --git a/interfaces/05-composition/time.go b/interfaces/05-composition/time.go new file mode 100644 index 0000000..ef7ff17 --- /dev/null +++ b/interfaces/05-composition/time.go @@ -0,0 +1,19 @@ +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/05-composition/types.go b/interfaces/05-composition/types.go new file mode 100644 index 0000000..6ea4882 --- /dev/null +++ b/interfaces/05-composition/types.go @@ -0,0 +1,23 @@ +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() float64 +} + +// TODO: NEW +// interface embedding +// When an interface includes multiple methods, +// choose a name that accurately describes its purpose. +type item interface { + printer + summer +}