Murali Manohar
Murali Manohar

Reputation: 613

Inheritance in Go

Why doesn't Go have Type Inheritance?

(The concept that when a class of an objects is defined, any subclass that is defined can inherit the definitions of one or more general classes)

Upvotes: 8

Views: 8872

Answers (4)

Invin
Invin

Reputation: 962

Just thought to add a few thoughts here. It is my opinion and hence a subjective and not an objective view. The simple answer is the fragility and complexity of inheritance(implementation inheritance) is not worth it in a language that is specially designed for server infrastructures that are easy to understand and maintain (you can maintain better if code is easy to understand). You can definitely achieve polymorphism in Go as it has interfaces and types can implement interfaces (by specifying a subset of interface methods). But creating deep inheritance hierarchies for code re-use leads to fragile and often spaghetti code that is difficult to maintain and reason about especially when the software gets bigger (which happens eventually to any successful/popular project). That's why you will notice that some of the modern languages have either avoided inheritance (Go, Rust etc) or disabled (Kotlin etc) it by default. One of the few places where inheritance use is considered good is GUI programming but even that is changing now. For example most of the modern GUI frameworks (React, Flutter) prefer composition over inheritance. Even Android is moving to composition style via jetpack-compose.

You can read this interview of Rob pike(co-creator of Go) why he didn't go for inheritance.
https://evrone.com/rob-pike-interview

Other links:
https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Issues_and_alternatives

https://reactjs.org/docs/composition-vs-inheritance.html

https://developer.android.com/jetpack/compose/tutorial

https://docs.flutter.dev/resources/architectural-overview#composition

Upvotes: 0

Zombo
Zombo

Reputation: 1

I think embedding fits the definition close enough:

package main
import "net/url"
type address struct { *url.URL }

func newAddress(rawurl string) (address, error) {
   p, e := url.Parse(rawurl)
   if e != nil {
      return address{}, e
   }
   return address{p}, nil
}

func main() {
   a, e := newAddress("https://stackoverflow.com")
   if e != nil {
      panic(e)
   }
   { // inherit
      s := a.String()
      println(s)
   }
   { // fully qualified
      s := a.URL.String()
      println(s)
   }
}

https://golang.org/ref/spec#Struct_types

Upvotes: -1

rox
rox

Reputation: 565

If you need inheritance for reusable, this example shows how I reuse the width/height of a shape interface,

package main

// compare to a c++ example: http://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm

import (
    "fmt"
)

// interface
type Shape interface {
    Area() float64
    GetWidth() float64
    GetHeight() float64
    SetWidth(float64)
    SetHeight(float64)
}

// reusable part, only implement SetWidth and SetHeight method of the interface
// {

type WidthHeight struct {
    width  float64
    height float64
}

func (this *WidthHeight) SetWidth(w float64) {
    this.width = w
}
func (this *WidthHeight) SetHeight(h float64) {
    this.height = h
}
func (this *WidthHeight) GetWidth() float64 {
    return this.width
}
func (this *WidthHeight) GetHeight() float64 {
    fmt.Println("in WidthHeight.GetHeight")
    return this.height
}

// }

type Rectangle struct {
    WidthHeight
}

func (this *Rectangle) Area() float64 {
    return this.GetWidth() * this.GetHeight() / 2
}

// override
func (this *Rectangle) GetHeight() float64 {
    fmt.Println("in Rectangle.GetHeight")
    // in case you still needs the WidthHeight's GetHeight method
    return this.WidthHeight.GetHeight()
}

func main() {
    var r Rectangle
    var i Shape = &r
    i.SetWidth(4)
    i.SetHeight(6)

    fmt.Println(i)
    fmt.Println("width: ",i.GetWidth())
    fmt.Println("height: ",i.GetHeight())
    fmt.Println("area: ",i.Area())

}

Result:

&{{4 6}}
width:  4
in Rectangle.GetHeight
in WidthHeight.GetHeight
height:  6
in Rectangle.GetHeight
in WidthHeight.GetHeight
area:  12

Upvotes: 8

Ainar-G
Ainar-G

Reputation: 36189

This was answered by the language creators in the F.A.Q.:

Object-oriented programming, at least in the best-known languages, involves too much discussion of the relationships between types, relationships that often could be derived automatically. Go takes a different approach.

Rather than requiring the programmer to declare ahead of time that two types are related, in Go a type automatically satisfies any interface that specifies a subset of its methods. Besides reducing the bookkeeping, this approach has real advantages. Types can satisfy many interfaces at once, without the complexities of traditional multiple inheritance. Interfaces can be very lightweight—an interface with one or even zero methods can express a useful concept. Interfaces can be added after the fact if a new idea comes along or for testing—without annotating the original types. Because there are no explicit relationships between types and interfaces, there is no type hierarchy to manage or discuss.

See also: Composition over inheritance principle.

Upvotes: 25

Related Questions