我正在使用具有类层次结构的C#代码库:
class Animal { Animal prey; }
class Mammal : Animal { Mammal[] livesAmicablyWith; }
class Lion : Mammal { }
原谅这个愚蠢的例子。
我想重新调整此类层次结构,以便以相同的对象格式表示,但需要更多数据。在我理想的世界里,它看起来像这样:
class Animal { Animal prey; string moreAnimalData; }
class Mammal : Animal { Mammal[] livesAmicablyWith; string moreMammalData; }
class Lion : Mammal { string moreLionData; }
但是,我想避免在现有的层次结构中添加成员,因为它们最多会浪费空间,最坏的情况是容易出错。
另外,我需要所有原始功能才能继续工作!这就是我的想法:
class AnimalExtended : Animal { }
class MammalExtended : Mammal {
public void UseLivesAmicablyWith()
{
foreach(Mammal m in livesAmicablyWith)
{
if(!(m is MammalExtended)
throw new Exception();
// use the MammalExtended
}
}
}
class LionExtended : Lion { }
这里有什么建议吗?
答案 0 :(得分:1)
基本上你要处理的是多重继承,当然你不能在C#中做到(关于那个,请参阅Stackoverflow上的很多问题)。
您的选择包括: -
移至界面:IAnimal
,IMammal
,ILion
并在引用这些项目时停止使用类。您现在可以创建丑陋的大型组合类,但只能使用IAnimal
或IAnimalExtended
来引用它,以便只显示相关属性。甚至可以更好地使用分组不同逻辑特征的接口也许ISocial
代替IAnimalExtended
,其中ISocial
定义了生物彼此之间的互动方式。
使用合成而不是继承:LionExtended
会公开Feeding
和SocialNature
的属性,这些属性不是在某个基础Animal
类中实现的在只处理一个问题的较小的类中。
同时执行:使用接口并使用合成而不是继承。
答案 1 :(得分:0)
我想这取决于你想要额外数据的“标准”程度。您可以简单地使用更多多态来实现结果:
interface IExtendedData
{
string GetMoreData<T>();
}
class ExtendedAnimal: Animal, IExtendedData
{
public virtual string GetMoreData<T>()
{
if (typeof(T) == typeof(Animal))
return "Extra animal data";
return String.Empty;
}
}
class ExtendedMammal: Mammal, IExtendedData
{
public override string GetMoreData<T>()
{
if (typeof(T) == typeof(Mammal))
return "Extra mammal data";
return base.GetMoreData<Animal>();
}
}
class ExtendedLion: Lion, IExtendedData
{
public override string GetMoreData<T>()
{
if (typeof(T) == typeof(Lion))
return "Extra lion data";
return base.GetMoreData<Mammal>();
}
}
在使用中,您可以动态转换为IExtendedData以非常地获取额外数据:
var mammal = getLion(); // Returns a lion...possibly an ExtendedLion, but possibly not
var extended = mammal as IExtendedData;
if (extended != null)
{
string mammalData = extended.GetMoreData<Mammal>();
string lionData = extended.GetMoreData<Lion>();
}
答案 2 :(得分:0)
我认为您所选择的方法是合理的,并且会起作用。我会尝试在添加值时(假设以某种方式封装)而不是在使用它们时进行类型检查(例如,添加到lifeAmicablywith的哺乳动物)。它会使错误更容易被捕获。
答案 3 :(得分:0)
我认为这是Decorator模式的一个很好的用例。您正在考虑的解决方案当然是朝这个方向发展的。