package
0.0.0-20230817172732-9976b92f604f
Repository: https://github.com/bootdotdev/fcc-learn-golang-assets.git
Documentation: pkg.go.dev

# README

Parametric Constraints

Your interface definitions, which can later be used as constraints, can accept type parameters as well.

// The store interface represents a store that sells products.
// It takes a type parameter P that represents the type of products the store sells.
type store[P product] interface {
	Sell(P)
}

type product interface {
	Price() float64
	Name() string
}

type book struct {
	title  string
	author string
	price  float64
}

func (b book) Price() float64 {
	return b.price
}

func (b book) Name() string {
	return fmt.Sprintf("%s by %s", b.title, b.author)
}

type toy struct {
	name  string
	price float64
}

func (t toy) Price() float64 {
	return t.price
}

func (t toy) Name() string {
	return t.name
}

// The bookStore struct represents a store that sells books.
type bookStore struct {
	booksSold []book
}

// Sell adds a book to the bookStore's inventory.
func (bs *bookStore) Sell(b book) {
	bs.booksSold = append(bs.booksSold, b)
}

// The toyStore struct represents a store that sells toys.
type toyStore struct {
	toysSold []toy
}

// Sell adds a toy to the toyStore's inventory.
func (ts *toyStore) Sell(t toy) {
	ts.toysSold = append(ts.toysSold, t)
}

// sellProducts takes a store and a slice of products and sells
// each product one by one.
func sellProducts[P product](s store[P], products []P) {
	for _, p := range products {
		s.Sell(p)
	}
}

func main() {
	bs := bookStore{
		booksSold: []book{},
	}
    
    // By passing in "book" as a type parameter, we can use the sellProducts function to sell books in a bookStore
	sellProducts[book](&bs, []book{
		{
			title:  "The Hobbit",
			author: "J.R.R. Tolkien",
			price:  10.0,
		},
		{
			title:  "The Lord of the Rings",
			author: "J.R.R. Tolkien",
			price:  20.0,
		},
	})
	fmt.Println(bs.booksSold)

    // We can then do the same for toys
	ts := toyStore{
		toysSold: []toy{},
	}
	sellProducts[toy](&ts, []toy{
		{
			name:  "Lego",
			price: 10.0,
		},
		{
			name:  "Barbie",
			price: 20.0,
		},
	})
	fmt.Println(ts.toysSold)
}

Assignment

The chief architect at Mailio has decided she wants to implement billing with generics. Specifically, she wants us to create a new biller interface. A biller is an interface that can be used to charge a customer, and it can also report its name.

There are two kinds of billers:

  • userBiller (cheaper)
  • orgBiller (more expensive)

A customer is either a user or an org. A user will be billed with a userBiller and an org with an orgBiller.

Create the new biller interface. It should have 2 methods:

  • Charge
  • Name

The good news is that the architect already wrote the userBiller and orgBiller types for us that fulfill this new biller interface. Use the definitions of those types and their methods to figure out how to write the biller interface definition starting on line 7.