Polymorphic copy: Difference between revisions

Go solution
(Factor)
(Go solution)
Line 586:
C
C
=={{header|Go}}==
Go does not have the terminology of polymorphism, classes, inheritance, derived types, or overriding.
 
It does however, have types, structs, interfaces, and methods. These language features are expressive enough to allow this task to be implemented.
 
In addition to the types t and s called for by the task description, I define two other types:
 
i, an interface type, is needed as a common "base" definition for the method. This is not Go terminology, and in fact notice that i is not even referenced anywhere in the definitions of types s or t. A "parent" method definition is called for by the task however, and interfaces are Go's way of doing this.
 
r, another type defined similarly to s, I added to illustrate that this analog of method inheritance and overriding is valid. (In Go terminology, that the method set of a type with an anonymous field includes the method set of the anonymous field.) You can see in the output that interface values of type r access t's identify method. Values of type s would as well, except s has it's own identify method which takes precedence.
<lang 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 t, 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))
}</lang>
Output:
<pre>
Initial (zero) values of interface variables:
i1: <nil>
i2: <nil>
i3: <nil>
 
Polymorphic:
i1: 5 / I'm a t! / main.t
i2: {6 one} / I'm an s! / main.s
i3: {7 0x0} / I'm a t! / main.r
 
First set now modified:
i1: {3 dog} / I'm an s! / main.s
i2: {1 0x0} / I'm a t! / main.r
i3: 2 / I'm a t! / main.t
 
Copies made before modifications:
i1c: 5 / I'm a t! / main.t
i2c: {6 one} / I'm an s! / main.s
i3c: {7 0x0} / I'm a t! / main.r
</pre>
 
=={{header|J}}==
 
1,707

edits