Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-interface methods in interface implementation

Tags:

oop

go

I have an interface which defines a method. I have a struct which implements this interface. In it, I have implemented the methods from this interface and also have additional methods defined.

For example:

package main

import (
    "fmt"
)   

type Animal interface {
    MakeNoise()
}

type Dog struct {
    color string
}

/* Interface implementation */

func (d *Dog) MakeNoise() {
    fmt.Println("Bark!")
}

/* End Interface implementation */

func (d *Dog) WagTail() {
    fmt.Println(d.color + " dog: Wag wag")
}

func NewDog(color string) Animal {
    return &Dog{color}
}

func main() {
    dog := NewDog("Brown")
    dog.MakeNoise()
    dog.WagTail()

}

On Playground: https://play.golang.org/p/B1GgoNToNl_l

Here, WagTail() is not part of the Animal interface but belongs to the Dog struct. Running this code gives an error

dog.WagTail undefined (type Animal has no field or method WagTail).

Is there a way I could have a struct adhere to an interface and also define it's own methods?

like image 327
Bharat Avatar asked Oct 23 '25 18:10

Bharat


2 Answers

This may help you.

d := dog.(*Dog)
d.WagTail()

On Playground: https://play.golang.org/p/KlNqpmvFTJi

like image 77
shal Avatar answered Oct 26 '25 07:10

shal


The error described it all:

dog.WagTail undefined (type Animal has no field or method WagTail)

To implement an interface you should implement all methods defined inside it.

dog := NewDog("Brown")
dog.MakeNoise()
dog.WagTail()

Now NewDog returns Animal interface which contains MakeNoise method but not WagTail.

The only way to manage your requirement is either create a variable of struct type Dog and then you can call any method having Dog as receiver.

d := &Dog{"Brown"}
d.WagTail()

Or you can return the pointer to Dog struct from NewDog method just like you did in your code mentioned in the comment as:

func NewDog(color string) *Dog {
    return &Dog{color}
}

But if the method is not defined in interface you cannot implement it using the struct as method receiver.

Golang provides a way in which:

You can ask the compiler to check that the type T implements the interface I by attempting an assignment using the zero value for T or pointer to T, as appropriate

type T struct{}
var _ I = T{}       // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.

If T (or *T, accordingly) doesn't implement I, the mistake will be caught at compile time.

If you wish the users of an interface to explicitly declare that they implement it, you can add a method with a descriptive name to the interface's method set. For example:

type Fooer interface {
    Foo()
    ImplementsFooer()
}

A type must then implement the ImplementsFooer method to be a Fooer, clearly documenting the fact and announcing it in godoc's output.

type Bar struct{}
func (b Bar) ImplementsFooer() {}
func (b Bar) Foo() {}

Most code doesn't make use of such constraints, since they limit the utility of the interface idea. Sometimes, though, they're necessary to resolve ambiguities among similar interfaces.

like image 40
Himanshu Avatar answered Oct 26 '25 07:10

Himanshu