oop Archives - Welcome To Golang By Example https://vikasboss.github.io/tag/oop/ Wed, 20 Jan 2021 05:24:11 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.1 https://i0.wp.com/golangbyexamples.com/wp-content/uploads/2021/05/cropped-go_border-1.png?fit=32%2C32&ssl=1 oop Archives - Welcome To Golang By Example https://vikasboss.github.io/tag/oop/ 32 32 159787465 Encapsulation in Go (Golang) https://vikasboss.github.io/encapsulation-in-go/ https://vikasboss.github.io/encapsulation-in-go/#comments Sat, 23 Nov 2019 08:12:35 +0000 https://vikasboss.github.io/?p=646 Golang provides encapsulation at the package level. Go doesn’t have any public,  private or protected keyword. The only mechanism to control the visibility is using the capitalized and non-capitalized formats Capitalized Identifiers...

The post Encapsulation in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
Golang provides encapsulation at the package level. Go doesn’t have any public,  private or protected keyword. The only mechanism to control the visibility is using the capitalized and non-capitalized formats

  • Capitalized Identifiers are exported. The capital letter indicates that this is an exported identifier.
  • Non-capitalized identifiers are not exported. The lowercase indicates that the identifier is not exported and will only be accessed from within the same package.

There are five kinds of identifier which can be exported or non-exported

  1. Structure
  2. Structure’s Method
  3. Structure’s Field
  4. Function
  5. Variable

Let’s see an example that shows exporting and non-exporting of all the above identifiers. See data.go below. The package is model

  • Structure
    • Struct Person is exported
    • Struct company is non-exported
  • Structure’s Method
    • Person Struct’s Method GetAge() is exported
    • Person Struct’s Method getName() is not exported
  • Structure’s Field
    • Person struct field Name is exported
    • Person struct field age is not exported
  • Function
    • Function GetPerson() is exported
    • Function getCompanyName() is not exported
  • Variables
    • Variable CompanyName is exported
    • Variable companyLocation is not exported

data.go

package model

import "fmt"

var (
    //CompanyName represents the company name
    CompanyName     = "test"
    companyLocation = "somecity"
)

//Person struct
type Person struct {
    Name string
    age  int
}

//GetAge of person
func (p *Person) GetAge() int {
    return p.age
}

func (p *Person) getName() string {
    return p.Name
}

type company struct {
}

//GetPerson get the person object
func GetPerson() *Person {
    p := &Person{
        Name: "test",
        age:  21,
    }
    fmt.Println("Model Package:")
    fmt.Println(p.Name)
    fmt.Println(p.age)
    return p
}

func getCompanyName() string {
    return CompanyName
}

Let’s write a file test.go in model package. See below.

test.go

package model

import "fmt"

//Test function
func Test() {
    //STRUCTURE IDENTIFIER
    p := &Person{
        Name: "test",
        age:  21,
    }
    fmt.Println(p)
    c := &company{}
    fmt.Println(c)
   
    //STRUCTURE'S METHOD
    fmt.Println(p.GetAge())
    fmt.Println(p.getName())
    
    //STRUCTURE'S FIELDS
    fmt.Println(p.Name)
    fmt.Println(p.age)
    
    //FUNCTION
    person2 := GetPerson()
    fmt.Println(person2)
    companyName := getCompanyName()
    fmt.Println(companyName)
    
    //VARIBLES
    fmt.Println(companyLocation)
    fmt.Println(CompanyName)
}

On running this file, it is able to access all exported and unexported fields in data.go as both lies in the same package model. There is no compilation error and it gives below output

Output:

&{test 21}
&{}
21
test
test
21
Model Package:
test
21
&{test 21}
test
somecity
test

Let’s move the above file test.go to a different package named view. Now notice the output on running ‘go build’. It gives compilation errors. All the compilation error are due to not able to refer to unexported fields

test.go

package view

import "fmt"

//Test function
func Test() {
    //STRUCTURE IDENTIFIER
    p := &model.Person{
        Name: "test",
        age:  21,
    }
    fmt.Println(p)
    c := &model.company{}
    fmt.Println(c)
    
    //STRUCTURE'S METHOD
    fmt.Println(p.GetAge())
    fmt.Println(p.getName())
    
    //STRUCTURE'S FIELDS
    fmt.Println(p.Name)
    fmt.Println(p.age)
    
    //FUNCTION
    person2 := model.GetPerson()
    fmt.Println(person2)
    companyName := model.getCompanyName()
    fmt.Println(companyName)
    
    //VARIBLES
    fmt.Println(model.companyLocation)
    fmt.Println(model.CompanyName)
}

Output:

test.go:13:3: unknown field 'age' in struct literal of type model.Person
test.go:17:8: cannot refer to unexported name model.company
test.go:17:8: undefined: model.company
test.go:22:15: p.getName undefined (cannot refer to unexported field or method model.(*Person).getName)
test.go:26:15: p.age undefined (cannot refer to unexported field or method age)
test.go:31:17: cannot refer to unexported name model.getCompanyName
test.go:31:17: undefined: model.getCompanyName
test.go:35:14: cannot refer to unexported name model.companyLocation
test.go:35:14: undefined: model.companyLocation

The post Encapsulation in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/encapsulation-in-go/feed/ 1 646
Compile Time Polymorphism in Go (Golang) https://vikasboss.github.io/compile-time-polymorphism-go/ https://vikasboss.github.io/compile-time-polymorphism-go/#comments Tue, 15 Oct 2019 02:27:30 +0000 https://vikasboss.github.io/?p=273 In compile-time polymorphism, the call is resolved during compile time by the compiler. Some of the  forms for compile-time polymorphism are Method/Function Overloading: more than one method/function exists with the same name but...

The post Compile Time Polymorphism in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
In compile-time polymorphism, the call is resolved during compile time by the compiler. Some of the  forms for compile-time polymorphism are

  • Method/Function Overloading: more than one method/function exists with the same name but with different signatures or possibly different return types
  • Operator Overloading: the Same operator is used for operating on different data types

Go doesn’t support Method Overloading. For example, see below program demonstrating that go doesn’t support method overloading.

package main

type maths struct{}

func (m *maths) add(a, b int) int {
    return a + b
}

func (m *maths) add(a, b, c int) int {
    return a + b + c
}

func main() {
   m := &maths{}
}

Output:

(*maths).add redeclared in this block
        previous declaration at ./main.go:5:6

Go also doesn’t support operator overloading. Reason for this is stated in faq of go – https://golang.org/doc/faq#overloading

Method dispatch is simplified if it doesn’t need to do type matching as well. Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go’s type system.
Regarding operator overloading, it seems more a convenience than an absolute requirement. Again, things are simpler without it.

Now the question is there any alternative to do method overloading in GO. This is where Variadic function in go comes into the picture. See below program

package main

import "fmt"

type maths struct{}

func (m *maths) add(numbers ...int) int {
    result := 0
    for _, num := range numbers {
        result += num
    }
    return result
}

func main() {
    m := &maths{}


    fmt.Printf("Result: %d\n", m.add(2, 3))
    fmt.Printf("Result: %d\n", m.add(2, 3, 4))
}

Output:

Result: 5
Result: 9

Conclusion:

Go doesn’t directly support method/function/operator overloading but variadic function provides a way of achieving the same with increased code complexity.

The post Compile Time Polymorphism in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/compile-time-polymorphism-go/feed/ 1 273
OOP: Inheritance in GOLANG complete guide https://vikasboss.github.io/oop-inheritance-golang-complete/ https://vikasboss.github.io/oop-inheritance-golang-complete/#comments Thu, 29 Aug 2019 01:37:34 +0000 https://vikasboss.github.io/?p=195 We will try to explain inheritance in GO using comparisons with inheritance in JAVA. The first thing we want to mention here is that GOLANG doesn’t have keywords such as “Extends” and...

The post OOP: Inheritance in GOLANG complete guide appeared first on Welcome To Golang By Example.

]]>
We will try to explain inheritance in GO using comparisons with inheritance in JAVA. The first thing we want to mention here is that GOLANG doesn’t have keywords such as “Extends” and “Implements” keyword as in JAVA. Go does provide limited functionalities of “Extends” and “Implements” keyword in a different way which each having its own limitations. Before we proceed to understand inheritance in GO there are some points worth mentioning.

  • Go prefers composition over inheritance. It allows embedding of struct into other struct.
  • Go does not support type inheritance.

We will start with the simplest of an example of inheritance in GO. Then we will list down a limitation or missing feature. In further iterations, we will fix limitation or keep adding missing features until we have written a program which shows all properties of inheritance possible/impossible in Go. So let’s start

The very basic use case of inheritance is child type should be able to access common data and methods of a parent type.  This is done in GO via embedding. The base struct is embedded in child struct and base’s data and methods can directly be accessed by child struct. See below code:  child struct is able to access the data “color” directly and also call the function “say()” directly. 

Program 1

package main
import "fmt"
type base struct {
    color string
}
func (b *base) say() {
    fmt.Println("Hi from say function")
}
type child struct {
    base  //embedding
    style string
}
func main() {
    base := base{color: "Red"}
    child := &child{
        base:  base,
        style: "somestyle",
    }
    child.say()
    fmt.Println("The color is " + child.color)
}

Output:

Hi from say function
The color is Red

One of the limitations of the above program is that you cannot pass the child type to a function that expects the base type as GO does not allow type inheritance. For example, the below code does not compile and gives an error – “cannot use child (type *child) as type base in argument to check”

Program 2

package main
import "fmt"
type base struct {
    color string
}
func (b *base) say() {
    fmt.Println("Hi from say function")
}
type child struct {
    base  //embedding
    style string
}
func check(b base) {
    b.say()
}
func main() {
    base := base{color: "Red"}
    child := &child{
        base:  base,
        style: "somestyle",
    }
    child.say()
    fmt.Println("The color is " + child.color)
    check(child)
}

Output:

cannot use child (type *child) as type base in argument to check

The above error tells basically that sub-typing is not possible in GO by just using embedding. Let’s try to fix this error. This is where GO interfaces come into the picture. See below version of the program which in addition to above functionalities also fixes this sub-typing error 

Program 3

package main
import "fmt"
type iBase interface {
    say()
}
type base struct {
    color string
}
func (b *base) say() {
    fmt.Println("Hi from say function")
}
type child struct {
    base  //embedding
    style string
}
func check(b iBase) {
    b.say()
}
func main() {
    base := base{color: "Red"}
    child := &child{
        base:  base,
        style: "somestyle",
    }
    child.say()
    fmt.Println("The color is " + child.color)
    check(child)
}

Output:

Hi from say function
The color is Red
Hi from say function

In the above program, we:    (a) Created an interface “iBase” which has “say” method    (b) We changed the “check” method to accept the argument of type iBase

Since base struct implements the “say” method and in turn, child struct embeds base. So the child method indirectly implements “say” method and becomes a type of “iBase” and that is why we can pass the child to the check function now. Great that we have fixed one limitation now using a combination of struct and interface. 
But there is one more limitation. Let’s say child and base both have one more function “clear” . Now “say” method makes a call to “clear” method. Then when “say” method is called using child struct, in turn, “say” method will call “clear” method of base and not “clear” method of the child. See below example

Program 4

package main
import "fmt"
type iBase interface {
    say()
}
type base struct {
    color string
}
func (b *base) say() {
    b.clear()
}
func (b *base) clear() {
    fmt.Println("Clear from base's function")
}
type child struct {
    base  //embedding
    style string
}
func (b *child) clear() {
    fmt.Println("Clear from child's function")
}
func check(b iBase) {
    b.say()
}
func main() {
    base := base{color: "Red"}
    child := &child{
        base:  base,
        style: "somestyle",
    }
    child.say()
}

Output:

Clear from base's function

As you can see above “clear” function of the base is called instead of“clear” method of the child. This is unlike Java where“clear” method of “child” would have been called.

One way to fix the above problem is to make “clear” as a property which is of type function in the base struct. This is possible in GO as functions are first-class variables in GO. See below solution

Program 5

package main
import "fmt"
type iBase interface {
    say()
}
type base struct {
    color string
    clear func()
}
func (b *base) say() {
    b.clear()
}
type child struct {
    base  //embedding
    style string
}
func check(b iBase) {
    b.say()
}
func main() {
    base := base{color: "Red",
        clear: func() {
            fmt.Println("Clear from child's function")
        }}
    child := &child{
        base:  base,
        style: "somestyle",
    }
    child.say()
}

Output:

Clear from child's function

Let’s try to add one more feature to the above program which is –

  • Multiple Inheritance – child struct should be able to access multiple properties and methods from two base struct and also sub-typing should be possible. Here is the code

Program 6

package main
import "fmt"
type iBase1 interface {
    say()
}
type iBase2 interface {
    walk()
}
type base1 struct {
    color string
}
func (b *base1) say() {
    fmt.Println("Hi from say function")
}
type base2 struct {
}
func (b *base1) walk() {
    fmt.Println("Hi from walk function")
}
type child struct {
    base1 //embedding
    base2 //embedding
    style string
}
func (b *child) clear() {
    fmt.Println("Clear from child's function")
}
func check1(b iBase1) {
    b.say()
}
func check2(b iBase2) {
    b.walk()
}
func main() {
    base1 := base1{color: "Red"}
    base2 := base2{}
    child := &child{
        base1: base1,
        base2: base2,
        style: "somestyle",
    }
    child.say()
    child.walk()
    check1(child)
    check2(child)
}

Output:

Hi from say function
Hi from walk function
Hi from say function
Hi from walk function

In the above program, the child embeds both base1 and base2. It can also be passed as an instance of iBase1 and iBase2 interface to the check1 and check2 function respectively. This is how we achieve multiple inheritance.

Now a big question is how do we implement “Type Hierarchy” in GO. As already mentioned type inheritance is not allowed to go and hence it does not have type hierarchy.GO intentionally doesn’t allow this feature so any change in the behavior of an interface is only propagated to its immediate structures which defines all methods of the interface. 

Although we can implement type hierarchy using interfaces and struct like below

Program 7

package main
import "fmt"
type iAnimal interface {
    breathe()
}
type animal struct {
}
func (a *animal) breathe() {
    fmt.Println("Animal breate")
}
type iAquatic interface {
    iAnimal
    swim()
}
type aquatic struct {
    animal
}
func (a *aquatic) swim() {
    fmt.Println("Aquatic swim")
}
type iNonAquatic interface {
    iAnimal
    walk()
}
type nonAquatic struct {
    animal
}
func (a *nonAquatic) walk() {
    fmt.Println("Non-Aquatic walk")
}
type shark struct {
    aquatic
}
type lion struct {
    nonAquatic
}
func main() {
    shark := &shark{}
    checkAquatic(shark)
    checkAnimal(shark)
    lion := &lion{}
    checkNonAquatic(lion)
    checkAnimal(lion)
}
func checkAquatic(a iAquatic) {}
func checkNonAquatic(a iNonAquatic) {}
func checkAnimal(a iAnimal) {}

See in above program how we are able to create a hierarchy (see below). This is the idiomatic way of go to create type hierarchy and we are able to achieve this by using embedding both on struct level and on the interface level. The point to be noted here is that if you want distinction in your type hierarchy where lets say a “shark”  should not be both “iAquatic” and “iNonAquatic”  , then there should be at least one method in the method sets of “iAquatic” and “iNonAquatic”  which is not present in the other. In our example “swim”  and “walk”  are those methods.

iAnimal
--iAquatic
----shark
--iNonAquatic
----lion

Conclusion:

Go doesn’t have support for type inheritance but the same can be achieved using embedding buts one needs to be careful while creating such kind of type hierarchy. Also, go does not provide method overriding.

The post OOP: Inheritance in GOLANG complete guide appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/oop-inheritance-golang-complete/feed/ 2 195
Abstract Class in GO: Complete Guide https://vikasboss.github.io/go-abstract-class/ https://vikasboss.github.io/go-abstract-class/#respond Sun, 18 Aug 2019 15:02:35 +0000 https://vikasboss.github.io/?p=203 Go Interface doesn’t have fields and also it doesn’t allow the definition of methods inside it. Any type needs to implements all methods of interface to become of that interface type. There...

The post Abstract Class in GO: Complete Guide appeared first on Welcome To Golang By Example.

]]>
Go Interface doesn’t have fields and also it doesn’t allow the definition of methods inside it. Any type needs to implements all methods of interface to become of that interface type. There are use cases where it is useful to have a default implementation of a method and also default fields in GO. Before understanding how to do it lets first understand the requirements of an abstract class:

  1. Abstract class should have default fields
  2. Abstract class should have the default method
  3. It should not be possible to create a direct instance of the abstract class

We will use a combination of a interface (abstract interface) and struct (abstract concrete type). Together they can provide the functionalities of an abstract class. See the below program:

package main

import "fmt"

//Abstract Interface
type iAlpha interface {
    work()
    common()
}

//Abstract Concrete Type
type alpha struct {
    name string
}

func (a *alpha) common() {
    fmt.Println("common called")
}

//Implementing Type
type beta struct {
    alpha
}

func (b *beta) work() {
    fmt.Println("work called")
    fmt.Printf("name is %s\n", b.name)
    b.common()
}

func main() {
    a := alpha{
        name: "test",
    }
    b := &beta{
        alpha: a,
    }
    b.work()
}

Output:

work called
name is test
common called

In above program:

  • We created an abstract interface iAlpha, an abstract concrete struct alpha, and an implementor struct beta
  • alpha struct is embedded in beta struct
  • The beta struct is able to access default field “name”
  • The beta struct is able to access the default method “common”
  • It is not able to create a direct instance of iAlpha  as alpha struct only implement only one of the method of iAlpha.

So it fulfills all three requirements but there is also one limitation of the above method. It is not possible to call the “work” method from “common” method of alpha. Basically there is no way to call an undefined method of the abstract interface from default methods of an abstract concrete type. There is one way to fix it, though. See below program

package main

import "fmt"

//Abstract Interface
type iAlpha interface {
    work()
    common()
}

//Abstract Concrete Type
type alpha struct {
    name string
    work func()
}

func (a *alpha) common() {
    fmt.Println("common called")
    a.work()
}

//Implementing Type
type beta struct {
    alpha
}

func (b *beta) work() {
    fmt.Println("work called")
    fmt.Printf("name is %s\n", b.name)
}

func main() {
    a := alpha{
        name: "test",
    }
    b := &beta{
        alpha: a,
    }
    b.alpha.work = b.work
    b.common()
}

Output:

common called
work called
name is test

In the above program:

  • We created a new field “work” of type func in alpha
  • We assigned alpha’s “work” method to beta “work” method

The only problem with the above program is that it is possible to create a direct instantiation of alpha struct and by providing the definition of work method, an instance of type iAlpha is created. This violates point 3 of the above Abstract class requirement as without creating our own new type we are able to create a type of iAlpha. Let’s try to fix this problem. The below program additionally also solves the problem where it was not possible to call the undefined methods from default methods.

package main

import "fmt"

//Abstract Interface
type iAlpha interface {
    work()
    common(iAlpha)
}

//Abstract Concrete Type
type alpha struct {
    name string
}

func (a *alpha) common(i iAlpha) {
    fmt.Println("common called")
    i.work()
}

//Implementing Type
type beta struct {
    alpha
}

func (b *beta) work() {
    fmt.Println("work called")
    fmt.Printf("Name is %s\n", b.name)
}

func main() {
    a := alpha{
        name: "test",
    }
    b := &beta{
        alpha: a,
    }
    b.common(b)
}

Output:

common called
work called
Name is test

In the above program:

  •  All the default methods will accept the first argument of interface type iAlpha. All the undefined methods of alpha struct will be called using this argument from default methods.

Conclusion: We can see in the above program that we are able to fulfill all three requirements of an abstract class. This is one of the ways to simulate abstract class in GO.

The post Abstract Class in GO: Complete Guide appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/go-abstract-class/feed/ 0 203