Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In golang, How can I override the embedded struct's method

Code here

package main

import "fmt"

func main() {
    t16()
}

type Base struct {
    val int
}
func (b *Base)Set(i int) {
    b.val = i
}
type Sub struct {
    Base
    changed bool
}

func (b *Sub)Set(i int) {
    b.val = i
    b.changed = true
}
func t16() {
    s := &Sub{}
    s.Base.Set(1)
    var b *Base = &s.Base
    fmt.Printf("%+v\n", b)
    fmt.Printf("%+v\n", s)
}

I want to make Sub act as Base, but when I call Set, for Sub it will mark the changed.I know there is no polymorphism or proxy in golang, but is there any way to do this, and not effect the Base?

UPDATED

I hope when I call Base.Set it will mark the change, for user, they don't know they actually use the Sub, so I can monitor the Base behave.

func t16() {
    s := &Sub{}
    var b *Base = &s.Base
    b.Set(10)
    fmt.Printf("%+v\n", b)
    fmt.Printf("%+v\n", s)
}
like image 986
wener Avatar asked Mar 16 '23 09:03

wener


1 Answers

By having Sub embed Base it automatically has all of Base's fields and functions made available as top level members of Sub. This means you can directly call s.val, and you would be able to call s.Set to invoke the base function except for the fact that Sub implemented its own Set method which hides the Base one.

When you call s.Base.Set() in your example you are bypassing Sub.Set() and directly calling Base.Set().

To fix it in your case is as simple as calling s.Set() instead of s.Base.Set().

This works for me:

func (b *Sub)Set(i int) {
    b.Base.Set(i)
    b.changed = true
}
func t16() {
    s := &Sub{}
    s.Set(1)
    var b *Base = &s.Base
    fmt.Printf("%+v\n", b)
    fmt.Printf("%+v\n", s)
}

Play link

Notice that Sub.Set() can invoke the embedded structs method as well, which feels a lot like the super() type inheritance that other oo languages provide.

like image 184
captncraig Avatar answered Apr 02 '23 14:04

captncraig