Monday, March 15, 2010

Classic Inheritance in Go Lang

Tar of this Project, extract and run make. Creates binary ChangeMe.app
BasicGoProject.tar.gz

Package and Imports

package main

import (
"fmt"
)

Interface that our Inheritance chain will implement. Analogous to an abstract Base Class in classic Object Oriented Terms.

// Declare an Interface to a 3d Solid
type Solid interface {
Volume() float
SurfaceArea() float
}

This is the base class for this chain of inheritance.

// Contains the Fields for defining a Rectangular Prism's Dimension's
type RectPrism struct {
l, w, h float
}

Implement the Solid Interface for RectPrism.

// RectPrism implements the Solid Interface
func (this *RectPrism) Volume() float {
return(this.l * this.w * this.h)
}

func (this *RectPrism) SurfaceArea() float {
return(2 * (this.l * this.w) + 2 * (this.l * this.h) + 2 * (this.w * this.h))
}

Here is Our first subclass of RectPrism. It inherits all the Fields and Methods attached to RectPrism by listing RectPrism as an anonymous Field. CardboardBox adds a Field aswell since CardboardBoxes can be Soggy.

type CardboardBox struct {
// An anonymous field, all fields of RectPrism are promoted into CardboardBox
RectPrism
isSoggy bool
}

An Open Topped Cardboard Box has to Reimplement the SurfaceArea Method of the Solid interface.

type OpenCardboardBox struct {
CardboardBox
}

We get to reuse the parent class's implementation of SurfaceArea and tack on the new Areas. This is how we use inheritance in Go for code reuse.

func (this *OpenCardboardBox) SurfaceArea() float {
return(this.CardboardBox.SurfaceArea() + 2 * (this.l * this.h) + 2 * (this.w * this.h))
}

And now we get to use an Open Cardboard Box and an Cardboard Box. They both implement the Solid interface so we can use interface's like in any other OO language.

func main() {

fmt.Printf("\n\n");

cbox := new(CardboardBox)
cbox.l = 2
cbox.w = 4
cbox.h = 2
cbox.isSoggy = true

obox := new(OpenCardboardBox)
obox.l = 2
obox.w = 4
obox.h = 2
obox.isSoggy = true

var rprism Solid = cbox
fmt.Printf(" Volume: %f\n", rprism.Volume())
fmt.Printf("Surface Area: %f\n", rprism.SurfaceArea())

rprism = obox
fmt.Printf(" Volume: %f\n", rprism.Volume())
fmt.Printf("Surface Area: %f\n", rprism.SurfaceArea())
fmt.Printf("\n\n");
}

One of the Main Differences between this and a true inheritance based implementation is that there is NO "is a" relationship in our chain. In the situation where we would need to check whether (OpenCardboardBox is a RectPrism) we would have to implement the "is a" relationship ourselves. The code might not be as pretty as that of a classic OO based language, but then again how often do we need the "is a" relationship?

3 comments:

  1. This is excellent demonstration of (in the java world) is extending an abstract class in go. It should have been in the go tour..

    Great post
    nz

    ReplyDelete
    Replies
    1. Thank you.

      I am about to start a personal project using Go and I will hopefully actually be able to dive in this time around.

      Delete
  2. Thank you very much. That was exactly the question I asked myself.

    ReplyDelete