I am trying to transfer my c ++ experience to the Go area. I'm new to Go, so not sure if the implementation is correct. In any case, it looks very ugly compared to C ++ code. Is there a nicer solution? Both solutions are executable in playground and give same result.
c++ playground: https://code.sololearn.com/c67xbW2AEWW2/#cpp
#include <iostream>
using namespace std;
// Abstract class
class AbstractGenerator
{
public:
AbstractGenerator() {}
std::string generate(std::string some_internal_data)
{
_some_internal_data = some_internal_data;
return step1() + step2();
}
protected:
// some shared fuctions
std::string generationHelper1(std::string s) { return s + _some_internal_data + "123"; }
std::string generationHelper2(std::string s) { return s + _some_internal_data + "456"; }
// abstract fucntions
virtual std::string step1() = 0;
virtual std::string step2() = 0;
private:
std::string _some_internal_data;
};
// Implementation
class MyGenerator : public AbstractGenerator
{
public:
MyGenerator() {}
protected:
std::string step1() override { return generationHelper1("my step1") + generationHelper2("my step1"); }
std::string step2() override { return "my step2"; }
};
int main() {
MyGenerator my_gen;
AbstractGenerator* abstract_gen = &my_gen;
cout << abstract_gen->generate("data");
return 0;
}
Go playground: https://play.golang.org/p/e3iXfYar4YJ
package main
import "fmt"
// some shared fuctions - interface
type ImplementationHelper interface {
generationHelper1(s string) string
generationHelper2(s string) string
}
// abstract fucntions - interface
type Implementation interface {
step1() string
step2() string
}
// Public main interface
type Generator interface {
Generate(s string) string
}
type AbstractGenerator struct {
someInternalData string
implementation Implementation
}
func NewAbstractGenerator(i Implementation) *AbstractGenerator {
g := new(AbstractGenerator)
g.implementation = i
return g
}
func (g *AbstractGenerator) Generate(s string) string {
g.someInternalData = s
return g.implementation.step1() + g.implementation.step2()
}
func (g *AbstractGenerator) generationHelper1(s string) string { return s + g.someInternalData + "123" }
func (g *AbstractGenerator) generationHelper2(s string) string { return s + g.someInternalData + "456" }
// Implementation of AbstractGenerator
type MyGenerator struct {
basic *AbstractGenerator
}
// MyGenerator constructor
func NewMyGenerator() *MyGenerator {
myGen := new(MyGenerator)
myGen.basic = NewAbstractGenerator(myGen)
return myGen
}
// Interface Generator
func (i *MyGenerator) Generate(s string) string {
return i.basic.Generate(s)
}
// Interface Implementation
func (i *MyGenerator) step1() string {
return i.basic.generationHelper1("my step1") + i.basic.generationHelper2("my step1")
}
func (i *MyGenerator) step2() string {
return "my step2"
}
func main() {
myGen := NewMyGenerator()
var abstractGen Generator
abstractGen = myGen
fmt.Println(abstractGen.Generate("data"))
}
NewMyGenerator
is really funny. It creates aMyGenerator
that is given to anAbstractGenerator
that in turn is registered as a delegate toMyGenerator
. That is not good. This complexity is unjustified. \$\endgroup\$