How to do simple inheritance in Go
I'm a Python developer trying to learn Go. I'm currently trying to refactor my first small project, but I'm not too sure how to use the method between structs.
Long story short, how would you do something like this Python code in Go?
class Super(object):
def CommonMethod(self):
print 'I am the common method.'
class One(Super):
def MethodOne(self):
self.CommonMethod()
print 'I am method one.'
class Two(Super):
def MethodTwo(self):
self.CommonMethod()
print 'I am method two.'
one = One()
one.MethodOne()
two = Two()
two.MethodTwo()
source to share
TL; DR
Go methods not only magically inherit subclasses like other languages ββlike Python or Java. You can define interfaces and use inlining, but you have to implement the methods required for each type. Of course, you can just call the inline method from an external method, however, be careful that any changes happen to the internal object and not the external one.
From the docs:
There's an important way in which nesting differs from subclassing. When we insert a type, methods of that type become methods of the outer type, but when they are called, the method receiver is the inner one, not the outer one. In our example, when
Read
method is abufio.ReadWriter
, it has exactly the same effect as the forwarding method above; the receiver is the field of the readerReadWriter
, not itselfReadWriter
.
Additional Information
Here are some links from the docs:
http://golang.org/doc/faq#Is_Go_an_object-oriented_language
Is object an object-oriented language?
Yes and no. While Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. the concept of "interface" in Go provides a different approach that we think is easier to use and in some ways more general. They are also ways of embedding types in other types in order to provide something similar, but not identical to the subclass.
So, you can have interfaces that define what a type should implement, but you have to implement those methods for each type.
You have one addition:
http://golang.org/doc/effective_go.html#embedding
Go does not provide the typical notion of type-driven subclassing, but it does have the ability to "borrow" parts of the implementation by embedding types within a structure or interface.
Interface nesting is very easy. We've mentioned
io.Reader
andio.Writer
interfaces before; here are their definitions.
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
The io package also exports several other interfaces that indicate objects that can implement several of these methods. For example, there
io.ReadWriter
, an interface containing bothRead
andWrite
. We can specifyio.ReadWriter
by specifying two methods explicitly, but it's easier and more memorable to implement two interfaces to form a new one, like this:
// ReadWriter is the interface that combines the Reader and Writer interfaces.
type ReadWriter interface {
Reader
Writer
}
source to share
Note: A recent article (today, Nov 18, 2014) titled " Subclassing in Go " illustrates some techniques for simulating "oo" behavior, languages ββsuch as java or python in go.
While composition is the norm, if you need the type " Parent
" to resolve a method call at runtime , you need a type Parent
to reference the interface.
Note that this does not provide "true" inheritance, though (as I explained in "Function-Behind Loading in GO Using Interfaces").
See Inheriting Semantics in Go for details .
type Person interface {
close() // define an interface to lookup methods on
flush()
}
type Parent struct {
self Person // retain reference to self for dynamic dispatch
}
func (p *Parent) flush() {
fmt.Println("parent flush")
}
func (p *Parent) close() {
p.self.flush() // call the flush method of whatever the child is.
fmt.Println("close")
}
So, you can "subclass" the parent type with the child type (insert the parent and reference it to self
):
type Child struct {
Parent
}
func (c *Child) flush() {
c.Parent.flush()
fmt.Println("child flush")
}
This means that if you create an instance of Child and put that instance in "self":
x := new(Child) x.self = x
Then the call x.close()
will print:
parent flush
child flush
close
source to share
Based on two comments on my question, I came up with the following solution in Go:
Go to the playing field: http://play.golang.org/p/JtPAON93PO
type Super struct{}
type One struct {
Super *Super
}
type Two struct {
Super *Super
}
func (s *Super) CommonMethod() {
fmt.Println("I am the common method.")
}
func (o *One) MethodOne() {
o.Super.CommonMethod()
fmt.Println("I am method one.")
}
func (t *Two) MethodTwo() {
t.Super.CommonMethod()
fmt.Println("I am method two.")
}
source to share