In object-oriented programming class is a set (a transitive closure) of types bound by the relation of inheritance. It is said that all types derived from some base type T and the type T itself form a class T.

The first type T from the class T sometimes is called the root type of the class.

A class of types itself, as a type, has the values and operations of its own.
The operations of are usually called methods of the root type.
Both operations and values are called  polymorphic.

A polymorphic operation (method) selects an implementation depending on the actual specific type of the polymorphic argument.

The action of choice the type-specific implementation of a polymorphic operation is called dispatch. Correspondingly, polymorphic operations are often called dispatching or virtual.
Operations with multiple arguments and/or the results of the class are called multi-methods.
A further generalization of is the operation with arguments and/or results from different classes.

 single-dispatch languages are those that allow only one argument or result to control the dispatch. Usually it is the first parameter, often hidden, so that a prefix notation x.f() is used instead of mathematical f(x).
 multiple-dispatch languages allow many arguments and/or results to control the dispatch.


A polymorphic value has a type tag indicating its specific type from the class and the corresponding specific value of that type.
This type is sometimes called the most specific type of a [polymorphic] value.
The type tag of the value is used in order to resolve the dispatch.
The set of polymorphic values of a class is a transitive closure of the sets of values of all types from that class.

In many  OO languages
the type of the class of T and T itself are considered equivalent.
In some languages they are distinct (like in Ada).
When class T and T are equivalent, there is no way to distinguish
polymorphic and specific values.



Task

Create a basic class with a method, a constructor, an instance variable and how to instantiate it.




package main
 
import "fmt"
 
// a basic "class."
// In quotes because Go does not use that term or have that exact concept.
// Go simply has types that can have methods.
type picnicBasket struct {
    nServings int // "instance variables"
    corkscrew bool
}
 
// a method (yes, Go uses the word method!)
func (b *picnicBasket) happy() bool {
    return b.nServings > 1 && b.corkscrew
}
 
// a "constructor."
// Also in quotes as Go does not have that exact mechanism as part of the
// language.  A common idiom however, is a function with the name new<Type>,
// that returns a new object of the type, fully initialized as needed and
// ready to use.  It makes sense to use this kind of constructor function when
// non-trivial initialization is needed.  In cases where the concise syntax
// shown is sufficient however, it is not idiomatic to define the function.
// Rather, code that needs a new object would simply contain &picnicBasket{...
func newPicnicBasket(nPeople int) *picnicBasket {
    // arbitrary code to interpret arguments, check resources, etc.
    // ...
    // return data new object.
    // this is the concise syntax.  there are other ways of doing it.
    return &picnicBasket{nPeople, nPeople > 0}
}
 
// how to instantiate it.
func main() {
    var pb picnicBasket          // create on stack (probably)
    pbl := picnicBasket{}        // equivalent to above
    pbp := &picnicBasket{}       // create on heap.  pbp is pointer to object.
    pbn := new(picnicBasket)     // equivalent to above
    forTwo := newPicnicBasket(2) // using constructor
    // equivalent to above.  field names, called keys, are optional.
    forToo := &picnicBasket{nServings: 2, corkscrew: true}
 
    fmt.Println(pb.nServings, pb.corkscrew)
    fmt.Println(pbl.nServings, pbl.corkscrew)
    fmt.Println(pbp)
    fmt.Println(pbn)
    fmt.Println(forTwo)
    fmt.Println(forToo)
}