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++
}
Related
This question comes form the porting I have to do from a working logic of C++ program, to a golang context.
This is just an example, and i see how wierd it can be, but think about the logic behind it.
If the explanation bores you, go to the code, it is pretty self explanatory.. otherwise I try to explain.
The concept is that I have a base class that contains a method with common logic, but that methot use virtual function that each descendant need to implement.
In go, I easly achieve inheritance of the base method, but the polimorphic adaptation to the descendant it's complicate (for me): I can't figure out how replicate this mechanism..
class TPolygon{
private:
int nside;
public:
TPolygon(int n){ nside=n; }
virtual float Area()=0;
float MeanArea(){ return Area()/nside; }
};
class TSquare: public TPolygon{
private:
float side;
public:
TSquare(float sidelen):TPolygon(4){ side=sidelen; }
float Area(){ return side*side; }
};
class TTriangle: public TPolygon{
private:
float base, height;
public:
TTriangle(float b, float h):TPolygon(3){ base=b; height=h; }
float Area(){ return base*height/2; }
};
TSquare *square=new TSquare(2.0);
square->MeanArea(); // -> 2*2 / 4 correct
TTriangle *triangle=new TTriangle(5.0, 6.0);
triangle->MeanArea(); // -> 5*6/2 / 3 correct
in go i tried:
type TPolygon struct {
nside int
}
func (p *TPolygon) Area() float64 {
return 0
}
func (p *TPolygon) MeanArea() float64 {
return p.Area() / float64(p.nside)
}
type TSquare struct {
TPolygon
side float64
}
func NewSquare(sidelength float64) *TSquare {
return &TSquare{
TPolygon: TPolygon{nside: 4},
side: sidelength,
}
}
func (s *TSquare) Area() float64 {
return s.side * s.side
}
type TTriangle struct {
TPolygon
base, height float64
}
func NewTriangle(b, h float64) *TTriangle {
return &TTriangle{
TPolygon: TPolygon{nside: 3},
base: b,
height: h,
}
}
func (t *TTriangle) Area() float64 {
return t.base * t.height / 2
}
square := NewSquare(2.0)
square.MeanArea() // -> 0 from TPolygon.Area()
The only way I found to achieve this, is a workaround that break the DRY principle because need to repeat the same method in each descendant
func (p *TPolygon) meanArea2(a float64) float64 {
return a / float64(p.nside)
}
func (s *TSquare) MeanArea2() float64 {
return s.meanArea2(s.Area())
}
func (t *TTriangle) MeanArea2() float64 {
return t.meanArea2(t.Area())
}
square.MeanArea2() // -> 1 as expected
and moreover, isn't always easy and possible to refactor this way, if the logic get more complicate..
Does anybody knows if this architecture is possible in golang, and how?
Or if there is other workaround that get close?
There are ways to emulate inheritance, but the following is much cleaner. It allows calculating the area/nsides value for any type that implements the two methods:
type MeanAreaSupport interface {
NSides() int
Area() float64
}
func MeanArea(shape MeanAreaSupport) float64 {
return shape.Area()/shape.NSides()
}
In glsl and hlsl, I can define a function like this:
float voronoi(vec2 x, out int2 cell) {
cell = ...
return ...
}
However, it doesn't seem like this is possible in wgsl.
What's the intended replacement for this? I guess I could define a VoronoiResult struct, but it seems overly boilerplate heavy:
struct VoronoiResult {
cell: vec2<i32>;
distance: f32;
};
fn voronoi(x: vec2<f32>) -> VoronoiResult {
// ...
var ret: VoronoiResult;
ret.distance = distance;
ret.cell = cell;
return ret;
}
The equivalent would be to use a pointer argument:
fn voronoi(x: vec2<f32>, cell: ptr<function, vec2<i32>>) -> f32 {
*cell = vec2(1, 2);
return 1.f;
}
#compute #workgroup_size(1)
fn main() {
var a: vec2<i32>;
var f = voronoi(vec2(1.f, 1.f), &a);
}
This produces the HLSL:
float voronoi(float2 x, inout int2 cell) {
cell = int2(1, 2);
return 1.0f;
}
[numthreads(1, 1, 1)]
void main() {
int2 a = int2(0, 0);
float f = voronoi((1.0f).xx, a);
return;
}
You can also make the struct version shorter by using the struct initializer:
struct Out {
cell: vec2<i32>,
val: f32,
}
fn voronoi(x: vec2<f32>) -> Out {
return Out(vec2(1, 2), 1.f);
}
#compute #workgroup_size(1)
fn main() {
var f = voronoi(vec2(1.f, 1.f));
}
I saw a piece of code as below:
Just wondering as the value method of draw() have been implemented, why could it return the pointer of the struct in fact.
type Shape interface {
draw()
}
type Rectangle struct {
}
func (Rectangle) draw() {
fmt.Println("Draw Rectangle")
}
type Square struct {
}
func (Squre) draw() {
fmt.Println("Draw Square")
}
type Circle struct {
}
func (Circle) draw() {
fmt.Println("Draw Circle")
}
type ShapeFactory struct {
}
func (*ShapeFactory) CreateShape(shape string) Shape {
if shape == "Rectangle" {
return &Rectangle{}
} else if shape == "Square" {
return &Square{}
} else if shape == "Circle" {
return &Circle{}
}
return nil
}
I think should it be like below to implement a pointer method so that the method CreateShape could return the pointer of struct?
type Rectangle struct {
}
func (*Rectangle) draw() {
fmt.Println("Draw Rectangle")
}
The return type defined on the CreateShape method is not a struct but an interface. Therefore CreateShape can return any type as long as it implements the Shape interface.
For example, if I have a bool value v, I want a reference to !v that can change when v changes. An example use will be:
class A {
bool& isOpen;
A(bool& value): isOpen(value) {}
void f() {
if (isOpen) {
doSomething();
}
}
};
class B {
bool& isClosed;
B(bool& value): isClosed(value) {}
void g() {
if (isClosed) {
doSomething();
}
}
};
int main() {
bool isOpen = true;
A a(isOpen);
B b(negattive_reference_of(isOpen));
a.f(); // doSomething()
b.g(); // do nothing
isOpen = false;
a.f(); // do nothing
b.g(); // doSomething()
}
Is there anyway in C++ to acheive a similar effect?
Under the hood reference is equivalent to a constant pointer to some variable (compiler just gives you a syntax sugar of how to work with such pointers so that they are always initialized).
So you wan't to have the same variable and two different pointers to it, one of which will dereference to true and the other to false. That is obviously impossible.
The OOP -way to do it would be to pass not reference to boolean but some interface to your classes and use implementation that uses same boolean variable:
class IIsOpenProvider
{
public:
virtual ~IIsOpenProvider() = 0;
virtual bool GetOpenValue() = 0;
};
class IIsClosedProvider
{
public:
virtual ~IIsClosedProvider() = 0;
virtual bool GetClosedValue() = 0;
};
class ValueProvider : public IIsOpenProvider, public IIsClosedProvider
{
public:
bool GetOpenValue() override { return isOpen; }
bool GetClosedValue() override { return !isOpen; }
private:
bool isOpen;
};
class A {
IIsOpenProvider& isOpen;
A(IIsOpenProvider& value): isOpen(value) {}
void f() {
if (isOpen.GetOpenValue()) {
doSomething();
}
}
};
class B {
IIsClosedProvider& isClosed;
B(IIsClosedProvider& value): isClosed(value) {}
void g() {
if (IIsClosedProvider.GetClosedValue()) {
doSomething();
}
}
};
// usage
ValueProvider val;
A a(val);
B b(val);
In g++ I could do this:
struct s
{
int a, b;
};
void MyFunction(s) { }
int main()
{
MyFunction((s) { 0, 0 });
return 0;
}
In Visual Studio however, it doesn't work. is there any way to make it work or some alternative syntax without making a variable and initializing it (and without adding a constructor to the struct as it will make it non-aggregate and it wouldn't be able to initialize in aggregates)?
My C is a bit rusty, but didn't you have to use struct s unless you typedef it? Something like this:
struct s
{
int a, b;
};
void MyFunction(struct s) { }
int main()
{
MyFunction((struct s) { 0, 0 });
return 0;
}
or
typedef struct s
{
int a, b;
} s_t;
void MyFunction(s_t) { }
int main()
{
MyFunction((s_t) { 0, 0 });
return 0;
}