RosettaCodeData/Task/Polymorphic-copy/Go/polymorphic-copy.go

85 lines
2.6 KiB
Go

package main
import (
"fmt"
"reflect"
)
// interface types provide polymorphism, but not inheritance.
type i interface {
identify() string
}
// "base" type
type t float64
// "derived" type. in Go terminology, it is simply a struct with an
// anonymous field. fields and methods of anonymous fields however,
// can be accessed without additional qualification and so are
// "inherited" in a sense.
type s struct {
t
kōan string
}
// another type with an "embedded" t field. (t is the *type*, this field
// has no *name*.)
type r struct {
t
ch chan int
}
// a method on t. this method makes t satisfy interface i.
// since a t is embedded in types s and r, they automatically "inherit"
// the method.
func (x t) identify() string {
return "I'm a t!"
}
// the same method on s. although s already satisfied i, calls to identify
// will now find this method rather than the one defined on t.
// in a sense it "overrides" the method of the "base class."
func (x s) identify() string {
return "I'm an s!"
}
func main() {
// three variables with different types, initialized from literals.
var t1 t = 5
var s1 s = s{6, "one"}
var r1 r = r{t: 7}
// variables declared with the same type. initial value is nil.
var i1, i2, i3 i
fmt.Println("Initial (zero) values of interface variables:")
fmt.Println("i1:", i1)
fmt.Println("i2:", i2)
fmt.Println("i3:", i3)
// in the terminology of the Go language reference, i1, i2, and i3
// still have static type i, but now have different dynamic types.
i1, i2, i3 = t1, s1, r1
fmt.Println("\nPolymorphic:")
fmt.Println("i1:", i1, "/", i1.identify(), "/", reflect.TypeOf(i1))
fmt.Println("i2:", i2, "/", i2.identify(), "/", reflect.TypeOf(i2))
fmt.Println("i3:", i3, "/", i3.identify(), "/", reflect.TypeOf(i3))
// copy: declare and assign in one step using "short declaration."
i1c, i2c, i3c := i1, i2, i3
// modify first set of polymorphic variables.
i1, i2, i3 = s{3, "dog"}, r{t: 1}, t(2)
// demonstrate that copies are distinct from first set
// and that types are preserved.
fmt.Println("\nFirst set now modified:")
fmt.Println("i1:", i1, "/", i1.identify(), "/", reflect.TypeOf(i1))
fmt.Println("i2:", i2, "/", i2.identify(), "/", reflect.TypeOf(i2))
fmt.Println("i3:", i3, "/", i3.identify(), "/", reflect.TypeOf(i3))
fmt.Println("\nCopies made before modifications:")
fmt.Println("i1c:", i1c, "/", i1c.identify(), "/", reflect.TypeOf(i1c))
fmt.Println("i2c:", i2c, "/", i2c.identify(), "/", reflect.TypeOf(i2c))
fmt.Println("i3c:", i3c, "/", i3c.identify(), "/", reflect.TypeOf(i3c))
}