【发布时间】:2020-04-07 06:01:55
【问题描述】:
来自Java背景,我无法理解如何使用Composition来实现继承或Composition如何解决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
我想在 Go 中使用组合来实现相同的功能。 毕竟这是公平的设计,应该可以很好地在 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
}
可以这样设计
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
}
谁能从 Go 设计的角度启发我实现这样的功能。
我的关注点/查询更多是围绕理解,如何使用组合来解决此类问题/代码可重用性以及更好的设计模式。
【问题讨论】:
-
组合和继承都可以用于代码重用,但它们并不相同。此外,组合不是用来实现继承的东西。不要试图模仿 Go 中的继承。
-
在 Go 中的接口是隐式实现的,
BaseCommand struct { ICommand }不是你要找的。您可以声明接口,声明接口的消费者,声明接口的具体实现并将它们传递给消费者。您可以使用嵌入来重用方法的常见或默认实现。就是这样。 -
基本上这个
func(c BaseCommand) LoadRecords() { info := c.GetInfo() },其中c.GetInfo()执行CommandABC的GetInfo方法是不可能没有尴尬的。你需要抛弃继承的心态,想出一种不同的方法来重用LoadRecords的逻辑。 -
这有助于让事情变得更清晰吗? play.golang.com/p/_-yg-pZ4QbV
-
在 Go 中重用代码的主要方法是提供 函数。获取接口值的函数和方法可以用于不同的类型。组合与继承只是一种设计转变。您也可以在 Java 中使用组合(与使用继承相比,它通常会导致代码不那么脆弱)。
标签: go inheritance composition