Coming from Java background, I am unable to understand how inheritance can be achieved using Composition or How composition solves some of the common solutions achieved by Inheritance?
interface ICommand {
void Save(Records data)
Records LoadRecords()
Info GetInfo()
}
abstract class BaseCommand : ICommand {
Records LoadRecords() {
var info = GetInfo()
//implement common method.
}
}
class CommandABC : BaseCommand {
Info GetInfo(){
return info;
}
void Save(Records data){
// implement
}
}
c = new CommandABC();
c.LoadRecords(); // BaseCommand.LoadRecords -> CommandABC.Info -> Return records
c.Save(); //Command ABC.Save
I want to achieve the same functionality in Go using composition. After all this is fair design and should be good to implement in Go.
type ICommand interface {
void Save(data Records)
LoadRecords() Records
GetInfo() Info
}
type BaseCommand struct {
ICommand //no explicit inheritance. Using composition
}
func(c BaseCommand) LoadRecords() {
info := c.GetInfo()
//implement common method
}
type CommandABC struct {
BaseCommand //Composition is bad choice here?
}
func(c CommandABC) Save(data Records) {
//implement
}
func(c CommandABC) GetInfo() Info {
//implement
}
func main(){
c := CommandABC{}
c.LoadRecords(); // BaseCommand.LoadRecords -> fails to call GetInfo since ICommand is nil
c.Save(); //Command ABC.Save
}
It can be made to work out like this
func main(){
c := CommandABC{}
c.ICommand = c //so akward. don't even understand why I am doing this
c.LoadRecords(); // BaseCommand.LoadRecords -> fails to call GetInfo since ICommand is nil
c.Save(); //Command ABC.Save
}
Can anyone enlighten me on achieving such functionality from Go design perspective.
My concerns/queries more around understanding, how to use composition for such problems/code reusability with better design patterns going forward.
You could do it a few different ways, but the most idiomatic is probably something along these lines. It's hard to give a detailed answer based on a contrived example with no details and most code elided, but I think this gets to where you're trying to go.
type Infoer interface {
GetInfo() Info
}
func LoadRecords(i Infoer) Records {
var info = i.GetInfo()
//implement common method.
}
type CommandABC struct {
info Info
}
func (c CommandABC) GetInfo() Info {
return c.info;
}
func (CommandABC) Save(data Records){
// implement
}
c := CommandABC{};
records := LoadRecords(c);
c.Save(records);