【发布时间】:2019-05-29 09:32:44
【问题描述】:
我仍在学习 Go 的做事方式,来自 C++ 背景。我正在寻找将 OOP 继承与接口组合进行对比的反馈。
我有一个 Go 程序的设计情况,如果我在 C++ 中实现,我会使用抽象基类来解决。
假设我需要一个基类,它有很多实现者。基类具有对抽象数据项起作用的共享方法。不同的 Worker 实现提供了对不同项目类型的 CRUD 操作,但 Worker 都使用基类的共享方法进行一般工作。
在 C++ 中我可能会这样做
class IItem
{
// virtual methods
};
class IWorker
{
public:
// one of many virtual functions that deal with IItem CRUD
virtual IItem* createItem() = 0;
// concrete method that works on interfaces
void doWork()
{
IItem* item = createItem();
// do stuff with an IItem*
}
};
class Toy : public IItem
{
};
// one of many kinds of workers
class ElfWorker : public IWorker
{
public:
ElfWorker()
{
// constructor implicitly calls IWorker()
}
IItem* createItem() override
{
return new Toy;
}
};
在 Go 中,您没有抽象的虚拟方法,例如 IWorker::createItem()。具体的类需要为基础提供一个接口或函数来做正确的事情。
所以我认为,必须使用指向 ElfWorker 的指针显式设置 ew.ItemCRUD 接口的 Go 代码。
精灵知道如何创建Item(),在他的例子中,它恰好是玩具对象。其他工作人员将为他们的数据对象实现他们自己的 ItemCRUD。
type Item interface {
// various methods
}
type ItemCRUD interface {
create() Item
// other CRUD
}
type Worker struct {
ItemCRUD // embedded interface
}
func (w *Worker) doWork() {
item := w.create()
// do stuff with item
}
type Toy struct {
}
type ElfWorker struct {
Worker // embedded
// ..
}
func NewElfWorker() *ElfWorker {
ew := &ElfWorker{}
ew.ItemCRUD = ew // <-- #### set Worker ItemCRUD explicitly ####
return ew
}
func (ew *ElfWorker) createItem() Item {
return &Toy{}
}
// more ElfWorker Item CRUD
func bigFunction(w *Worker) {
// ...
w.doWork()
// ..
}
所以我有点纠结的部分是显式设置。如果我希望基础 Worker 类在 Items 上提供共享方法,那么组合的“Go way”似乎确实需要这个 explicit 步骤。
想法?
【问题讨论】:
-
在 C++ 和任何其他语言之间进行比较可能会适得其反。
-
@Ron 评论的一阶导数:将其他编程语言中的模式应用于 Go 可能会适得其反。
-
我投票结束这个问题,因为它应该被移到 Codereview
-
因为我要求对设计选择提供反馈而投反对票?我想我明确表示我想学习?我预先说明了语言会以不同的方式解决问题。
标签: go virtual composition