Object serialization: Difference between revisions

Content added Content deleted
(→‎{{header|Go}}: updates for two library changes)
(→‎{{header|Go}}: task conformance: polymorphic func prints rather than returns string. Also a bug fix, more readable object initialization, and a rewrite of the introduction.)
Line 499: Line 499:
Go has a few choices for serialization. The method shown here is the native method, which is compact and type-aware.
Go has a few choices for serialization. The method shown here is the native method, which is compact and type-aware.


A note on object oriented stuff, while I implemented object hierarchy required by the task description with embedded structs, this method offers no polymorphism. The polymorphism required by the task description was for printing, which Go handles nicely with interfaces, and in fact, with an interface type already defined in the fmt package. Thus my polymorphic collection is not a collection based on the common root of the object hierarchy, but on this common interface, fmt.Stringer.
A note on object oriented stuff, the object hierarchy required by the task description is implemented here with embedded structs. The polymorphism required by the task description is handled nicely with an interface. The functional polymorphism is orthogonal to the object hierarchy, not conflated with it.
<lang go>package main
<lang go>package main


Line 507: Line 507:
"os"
"os"
)
)

type printable interface {
print()
}


func main() {
func main() {
// create instances
// create instances
animals := []fmt.Stringer{
animals := []printable{
&animal{true},
&Animal{Alive: true},
&cat{},
&Cat{},
&lab{dog{animal{true}, false}, "yellow"},
&Lab{
&collie{dog{animal{true}, true}, false},
Dog: Dog{Animal: Animal{Alive: true}},
Color: "yellow",
},
&Collie{Dog: Dog{
Animal: Animal{Alive: true},
ObedienceTrained: true,
}},
}
}


Line 520: Line 530:
fmt.Println("created:")
fmt.Println("created:")
for _, a := range animals {
for _, a := range animals {
fmt.Println(" ", a)
a.print()
}
}


Line 545: Line 555:
return
return
}
}
var clones []fmt.Stringer
var clones []printable
gob.NewDecoder(f).Decode(&clones)
gob.NewDecoder(f).Decode(&clones)
if err != nil {
if err != nil {
Line 555: Line 565:
fmt.Println("\nloaded from objects.dat:")
fmt.Println("\nloaded from objects.dat:")
for _, c := range clones {
for _, c := range clones {
fmt.Println(" ", c)
c.print()
}
}
}
}


type animal struct {
type Animal struct {
Alive bool
Alive bool
}
}


func (a *animal) String() (r string) {
func (a *Animal) print() {
if a.Alive {
if a.Alive {
r = "live"
fmt.Println(" live animal, unspecified type")
} else {
} else {
r = "dead"
fmt.Println(" dead animal, unspecified type")
}
}
return r + " animal, unspecified type"
}
}


type dog struct {
type Dog struct {
animal
Animal
ObedienceTrained bool
ObedienceTrained bool
}
}


func (d *dog) String() string {
func (d *Dog) print() {
r := "dog"
switch {
if !d.Alive {
case !d.Alive:
return "dead " + r
fmt.Println(" dead dog")
case d.ObedienceTrained:
}
fmt.Println(" trained dog")
if d.ObedienceTrained {
default:
return "trained " + r
fmt.Println(" dog, not trained")
}
}
return r + ", not trained"
}
}


type cat struct {
type Cat struct {
animal
Animal
LitterBoxTrained bool
LitterBoxTrained bool
}
}


func (c *cat) String() string {
func (c *Cat) print() {
r := "cat"
switch {
if !c.Alive {
case !c.Alive:
return "dead " + r
fmt.Println(" dead cat")
case c.LitterBoxTrained:
fmt.Println(" litter box trained cat")
default:
fmt.Println(" cat, not litter box trained")
}
}
if c.LitterBoxTrained {
return "litter box trained " + r
}
return r + ", not litter box trained"
}
}

type lab struct {
type Lab struct {
dog
Dog
Color string
Color string
}
}

func (l *lab) String() string {
func (l *Lab) print() {
r := "lab"
var r string
if l.Color == "" {
if l.Color == "" {
r += ", color unspecified"
r = "lab, color unspecified"
} else {
} else {
r = l.Color + " lab"
r = l.Color + " lab"
}
switch {
case !l.Alive:
fmt.Println(" dead", r)
case l.ObedienceTrained:
fmt.Println(" trained", r)
default:
fmt.Printf(" %s, not trained\n", r)
}
}
if !l.Alive {
return "dead " + r
}
if l.ObedienceTrained {
return "trained " + r
}
return r + ", not trained"
}
}


type collie struct {
type Collie struct {
dog
Dog
CatchesFrisbee bool
CatchesFrisbee bool
}
}

func (c *collie) String() string {
func (c *Collie) print() {
r := "collie"
if !c.Alive {
return "dead " + r
}
switch {
switch {
case !c.Alive:
fmt.Println(" dead collie")
case c.ObedienceTrained && c.CatchesFrisbee:
case c.ObedienceTrained && c.CatchesFrisbee:
r = "trained " + r + ", catches frisbee"
fmt.Println(" trained collie, catches frisbee")
case c.ObedienceTrained && !c.CatchesFrisbee:
case c.ObedienceTrained && !c.CatchesFrisbee:
r = "trained " + r + ", but doesn't catch frisbee"
fmt.Println(" trained collie, but doesn't catch frisbee")
case !c.ObedienceTrained && c.CatchesFrisbee:
case !c.ObedienceTrained && c.CatchesFrisbee:
r += ", not trained, but catches frisbee"
fmt.Println(" collie, not trained, but catches frisbee")
case !c.ObedienceTrained && !c.CatchesFrisbee:
case !c.ObedienceTrained && !c.CatchesFrisbee:
r += ", not trained, doesn't catch frisbee"
fmt.Println(" collie, not trained, doesn't catch frisbee")
}
}
return r
}</lang>
}</lang>
Output:
Output: