People are saying, Go is not an OO (Object Oriented) language; don't use OO terms on Go. OK, let me describe what I am able to do with OO --
With an OO language, I can make different animals say different things based on their classes:
cat.Say() // miao
sheep.Say() // bahh
cow.Say() // moo
The same is getting the Area() from Shapes.
However, this go demo code made me believe that it is impossible. Included below as Exhibit#1.
Then today, I found this go demo code, which makes it entirely possible. Included below as Exhibit#2.
So my question is, what's fundamentally different between the two, that makes the first one wrong and second one correct? How to make the first one "works"?
Exhibit#1:
// Credits: hutch
// https://groups.google.com/d/msg/golang-nuts/N4MBApd09M8/0ij9yGHK_8EJ
////////////////////////////////////////////////////////////////////////////
/*
https://groups.google.com/d/msg/golang-nuts/N4MBApd09M8/tOO5ZXtwbhYJ
LRN:
Subtype polymorphism: Not applicable (Go doesn't have subtyping).
Although if you embed a struct A implementing interface X into a struct B,
struct B will implement interface X, and can be used instead of struct A in
places where struct A is expected. So, kind of yes.
Robert Johnstone:
interfaces behave similarly to virtual functions, but they are not identical. See the (following) example program by hutch.
*/
package main
import "fmt"
type A struct {
astring string
}
type B struct {
A
bstring string
}
type Funny interface {
strange()
str() string
}
func (this *A) strange() {
fmt.Printf("my string is %q
", this.str())
}
func (this *A) str() string {
return this.astring
}
func (this *B) str() string {
return this.bstring
}
func main() {
b := new(B)
b.A.astring = "this is an A string"
b.bstring = "this is a B string"
b.strange()
// Output: my string is "this is an A string"
// Many people familiar with OO (and unfamiliar with Go) will be quite
// surprised at the output of that program.
}
Exhibit#2:
// Credits: https://play.golang.org/p/Zn7TjiFQik
////////////////////////////////////////////////////////////////////////////
/*
Problem (From Polymorphism-Subtype.go):
https://groups.google.com/d/msg/golang-nuts/N4MBApd09M8/tOO5ZXtwbhYJ
LRN: Subtype polymorphism: Not applicable (Go doesn't have subtyping).
Goal:
This is to demo that "polymorphism" is still doable in Go.
*/
package main
import (
"fmt"
)
type Shape interface {
Area() float32
}
type Point struct {
x float32
y float32
}
// Make sure the structs are different sizes so we're sure it'll work with
// all sorts of types
type Circle struct {
center Point
radius float32
}
func (c Circle) Area() float32 {
return 3.1415 * c.radius * c.radius
}
type Rectangle struct {
ul Point
lr Point
}
func (r Rectangle) Area() float32 {
xDiff := r.lr.x - r.ul.x
yDiff := r.ul.y - r.lr.y
return xDiff * yDiff
}
func main() {
mtDict := make(map[string]Shape)
// No problem storing different custom types in the multitype dict
mtDict["circ"] = Circle{Point{3.0, 3.0}, 2.0}
mtDict["rect"] = Rectangle{Point{2.0, 4.0}, Point{4.0, 2.0}}
for k, v := range mtDict {
fmt.Printf("[%v] [%0.2f]
", k, v.Area())
}
}
/*
$ go run Polymorphism-Shape.go
[circ] [12.57]
[rect] [4.00]
*/