依赖于姐妹类的类的实现

Implementation of a class which depends on a sister class

本文关键字:实现 姐妹 依赖于      更新时间:2023-10-16

我有多个,比如说2个,从抽象基类派生的类,比如Ingredient。现在,CarrotPotato通过公共继承实现了Ingredient的纯虚拟函数(称为Taste())。现在,假设我想要一个类Salt,它是Ingredient(也就是说,它是从它派生的),但需要调用其姊妹类的Taste()实现?

基本上,Salt类稍微修改了其姊妹类的Taste()实现。这能实现吗?如果是,如何?

这是我想做的事情的草图:

class Ingredient {
virtual void Taste() = 0;
};
class Carrot : public Ingredient {
void Taste() { printf("Tastes like carrot");}
};
class Potato : public Ingredient {
void Taste() { printf("Tastes like potato"); }
};
class Salt : public Ingredient {
void Taste() { SisterClass->Taste(); printf(" but salty"); }
};

盐本身无法合理地提供改良的味道:它需要一种真正的其他成分来盐。但其他成分是什么?事实上,有"有东西,但有咸味"的不是盐,而是一种咸味制剂,含有另一种成分。这可以通过以下几种方式进行建模:

组成

这种制剂实际上包含了其他成分,并代表了呼叫。

class SaltedPreparation : public Ingredient {
Ingredient *baseIngredient;
void Taste() { baseIngredient->Taste(); printf(" but salty"); }
};

Tomato tomato;
SaltedPreparation preparation;
preparation.baseIngredient = &tomato;
preparation.Taste();

继承

腌番茄还是番茄,不是吗?这取决于与成分相同的原理,但成分本身是盐。我想。

class SaltedTomato : public Tomato {
void Taste() { Tomato::Taste(); printf(" but salty"); }
};

SaltedTomato tomato;
tomato.Taste();

Mixin

我不喜欢每次需要调味时都写新课程,所以让我们为此写一个模板吧!Mixin模式是对现有类进行此类通用修改的典型模式。

template <class BaseIngredient>
class Salted : public BaseIngredient {
void Taste() { BaseIngredient::Taste(); printf(" but salty"); }
};

Salted<Tomato> tomato;
tomato.Taste();

复合材料

上述所有模型都忽略了盐本身也是一种成分的事实。这可能很好,但如果必须这样做怎么办?那么复合模式可能会很有用。让我们把调味料和主料区分开,因为我们不喜欢咸盐。

class Seasoning : public Ingredient { };
class Salt : public Seasoning {
void Taste() { printf("salty"); }
};
class SeasonedPreparation : public Ingredient {
Ingredient *ingredient;
Seasoning *seasoning;
void Taste() { ingredient->Taste(); printf(", but "); seasoning->Taste(); }
};

Tomato tomato;
Salt salt;
SeasonedPreparation preparation;
preparation.ingredient = &tomato;
preparation.seasoning = &salt;
preparation.Taste();

我现在有点饿。

Salt无法修改其他类的实现。但是Salt可以被赋予一个指向另一个Ingredient的指针来进行操作,例如:

class Salt : public Ingredient
{
private:
Ingredient *OtherIngredient;
public:
Salt(Ingredient *AOther) : OtherIngredient(AOther) {}
virtual void Taste() { OtherIngredient->Taste(); printf(" but salty"); }
};

然后你可以这样做:

Potato potato;
Salt salt(&potato);
salt.Taste();

但这真的没有道理,是吗?盐尝起来不像土豆,但土豆可以尝起来很咸。因此,我可能会采取不同的方法:

#include <vector>
class Ingredient 
{
public:
virtual void Taste() = 0;
};
class Seasoning : public Ingredient 
{
};
class SeasonableIngredient : public Ingredient 
{
protected:
std::vector<Seasoning*> seasonings;
virtual void TastesLike() = 0;
public:
virtual void Taste()
{
printf("Tastes like ");
TastesLike();
if (!seasonings.empty())
{
std::vector<Seasoning*>::iterator iter = seasonings.begin();
printf(" but ");
iter->Taste();
++iter;
while (iter != seasonings.end())
{
printf(" and ");
iter->Taste();
++iter;
}
}
}
void AddSeasoning(Seasoning *seasoning) { seasonings.push_back(seasoning); }
};
class Carrot : public SeasonableIngredient
{
protected:
virtual void TastesLike() { printf("carrot"); }
};
class Potato : public SeasonableIngredient
{
protected:
virtual void TastesLike() { printf("potato"); }
};
class Salt : public Seasoning
{
public:
void Taste() { printf("salty"); }
};
class Pepper : public Seasoning
{
public:
void Taste() { printf("peppery"); }
};

Potato potato;
Salt salt;
Pepper pepper;
Potato.AddSeasoning(&salt);
Potato.AddSeasoning(&pepper);
potato.Taste();