我在C++方面有比Go更多的經驗。我試圖理解如何在Go中慣用地表達Composite design pattern,特別是參考了屬性。在C++中,我將使用父類來保存一組子類通用的屬性和方法。我沒有看到這在Go中如何工作。一個接口允許我定義要實現的方法,但它不允許我提供默認實現。我必須在實現接口的每個結構中重新實現該方法,並複製每個結構中的所有屬性。我無法在接口中保留常用屬性,因爲接口沒有數據元素。你如何在Go中進行這種重構?相當於子類的習語轉到
這裏的(在C++)什麼,我想能在去做一個例子:
#include <string>
/*
* Parent class for edible things. Holds the "name" attribute.
*/
class Edible {
public:
Edible(const std::string &aName):
ed_Name(aName) { }
const std::string &name() const { return ed_Name; }
protected:
void setName(const std::string &aName) { ed_Name = aName; }
private:
std::string ed_Name;
};
/*
* Subclass of Edible for fruits. Depends on Edible to store the name.
*/
class Fruit: public Edible {
public:
Fruit(const std::string &aName,
const std::string &aPlant):
Edible(aName),
fr_Plant(aPlant) { }
const std::string &plant() const { return fr_Plant; }
protected:
void setPlant(const std::string &aPlant) { fr_Plant = aPlant; }
private:
std::string fr_Plant;
};
/*
* Subclass of Edible for meats. Depends on Edible to store the name.
* Has attributes for the animal and the cut of meat.
*/
class Meat: public Edible {
public:
Meat(const std::string &aName,
const std::string &aAnimal,
const std::string &aCut):
Edible(aName),
me_Animal(aAnimal),
me_Cut(aCut) { }
const std::string &animal() const { return me_Animal; }
const std::string &cut() const { return me_Cut; }
protected:
void setAnimal(const std::string &aAnimal) { me_Animal = aAnimal; }
void setCut(const std::string &aCut) { me_Cut = aCut; }
private:
std::string me_Animal;
std::string me_Cut;
};
Go沒有繼承,所以type層次通常是你想要避免的東西。 C++/Java設計模式不適合Go中使用的結構類型和組合。 – JimB
在Go中搜索嵌入,並閱讀推薦的設計模式。正如JimB所說,你想重新考慮一下設計,從我來描述它的最簡單的方式是繼承關係是顛倒的。你永遠不會繼承,你只能撰寫/嵌入。除此之外,當你使用父類型實現多態行爲時,比如迭代'[] ParentType'並調用'MethodThatsOverriden()',你需要定義一個接口並使用它。 – evanmcdonnal