As it is just composition, it is strictly better than inheritance, but still probably unnecessarily confusing versus just writing out the delegation methods yourself.
My mistake. I was mislead by the blog post.
From the article:
> The new type would be interchangeable with the existing client which would minimize the need for changes to existing code.
So with go exported structs it is not fair to say they can be used interchangeably if at any point that instance is used as a parameter, field, or variable that defines the type?
In the examples given in the article, the thing that is used as parameters is the interface Client not the concrete type HTTPClient. Would that not allow CachedHTTPClient to passed around as if it was a Client and would that not show the same issues as inheritance?
public interface Client {
ArrayList<String> getUsers();
void createUser(String name);
}
public class HTTPClient implements Client {
public ArrayList<String> getUsers() { /* ... */ }
public void createUser(String name) { /* ... */ }
}
public class CachedHTTPClient implements Client {
private HTTPClient httpClient;
public ArrayList<String> getUsers() { /* ... */ }
// In Go via "struct embedding", this method would be generated
// automatically; in Java, we have to write it out. NBD.
public void createUser(String name) { this.httpClient.createUser(name); }
}Literally all it does is automatically create methods on the outer struct that delegate to the anonymous member.
Unlike inheritance, there is no fragile base class problem and methods on the inner anonymous member can’t dispatch to methods on the outer struct. Also, the “parent” member is just another field in your struct. You can modify it or replace it at runtime, unlike the parent in OOP languages.