消除方法重复

Is it possible to refactor the following code to eliminate the duplication?

I want my GameObject implement the logic for "update" task invoking different update handlers (like my "AfterUpdate"). The current version works, but there are two implementations of "Update" and they are equal. AfterUpdate invoked on GameObject should operate on its properties, AfterUpdate invoked on HeroGameObject should have access to HeroGameObject's properties (like "health" for example).

What can I do better? Thank you.

package main

import "fmt"

type Point struct {
    x, y int
}

///////////////////////
type GameObject struct {
    Point
    title       string
    status      int
    ticks       float32
    spriteIndex int
}

func (g *GameObject) Update() {

    if g.ticks == 0 {

        g.spriteIndex++
        g.AfterUpdate()
    }
}

func (g *GameObject) AfterUpdate() {
    g.status = 0 //suppose it does something meaningful
    fmt.Println("GameObject afterUpdate handler invoked")
}

///////////////////////
type HeroGameObject struct {
    GameObject
    health float32
}

func (h *HeroGameObject) Update() {

    if h.ticks == 0 {

        h.spriteIndex++
        h.AfterUpdate()
    }
}

func (h *HeroGameObject) AfterUpdate() {
    h.health-- //suppose it does something meaningful but *different*, using its own properties, for example "health"
    fmt.Println("HeroGameObject afterUpdate handler invoked")
}

///////////////////////
func main() {

    gameObject := &GameObject{
        Point: Point{
            x: 0,
            y: 0,
        },
        title:       "dummy object",
        status:      0,
        ticks:       0,
        spriteIndex: 0,
    }

    heroObject := &HeroGameObject{
        GameObject: GameObject{
            Point: Point{
                x: 0,
                y: 0,
            },
            title:       "hero object",
            status:      0,
            ticks:       0,
            spriteIndex: 0,
        },
        health: 0,
    }

    gameObject.Update()
    heroObject.Update()
}

The output:

GameObject afterUpdate handler invoked

HeroGameObject afterUpdate handler invoked

UPDATED I've come up with the following solution and I wonder what do you think:

package main

import "fmt"

type Point struct {
    x, y int
}

///////////////////////
type IHandler interface {
    afterUpdate()
}

type GameObject struct {
    Point
    title       string
    status      int
    ticks       float32
    spriteIndex int
    handler IHandler
}

func (g *GameObject) SetHandler(h IHandler) {
    g.handler = h
}

func (g *GameObject) Update() {

    if g.ticks == 0 {

        g.spriteIndex++
        if g.handler != nil {
            g.handler.afterUpdate()
        }
    }
}

//actually it is IHandler specific implementation number one
func (g *GameObject) afterUpdate() {
    g.status = 0 //suppose it does something meaningful
    fmt.Println("GameObject afterUpdate handler invoked")
}

///////////////////////
type HeroGameObject struct {
    GameObject
    health float32
}

// note, this method is commented out
/*
func (h *HeroGameObject) Update() {

    if h.ticks == 0 {

        h.spriteIndex++
        h.AfterUpdate()
    }
}*/

//actually it is IHandler specific implementation number two
func (h *HeroGameObject) afterUpdate() {
    h.health-- //suppose it does something meaningful but *different*, using its own properties, for example "health"
    fmt.Println("HeroGameObject afterUpdate handler invoked")
}

///////////////////////
func main() {

    gameObject := &GameObject{
        Point: Point{
            x: 0,
            y: 0,
        },
        title:       "dummy object",
        status:      0,
        ticks:       0,
        spriteIndex: 0,
    }
    gameObject.SetHandler(gameObject) //!

    heroObject := &HeroGameObject{
        GameObject: GameObject{
            Point: Point{
                x: 0,
                y: 0,
            },
            title:       "hero object",
            status:      0,
            ticks:       0,
            spriteIndex: 0,
        },
        health: 0,
    }
    heroObject.SetHandler(heroObject) //!

    gameObject.Update()
    heroObject.Update()
}

http://play.golang.org/p/GIwOknSSzx

Is it okay to have "gameObject.SetHandler(gameObject)"?

How about using flag function and base interface, like this?

type BaseGameObject interface {
    Ticks() int
    IncSpriteIndex()
    AfterUpdate()
}

func UpdateGameObject(o BaseGameObject) {
    if o.Ticks() == 0 {
        o.IncSpriteIndex()
        o.AfterUpdate()
    }
}

func (o *GameObject) Ticks() int {
    return o.ticks
}

func (o *GameObject) IncSpriteIndex() {
    o.spriteIndex++
}