C# 如何扩展对象层次结构以容纳额外数据?
我在一个具有类层次结构的C#代码库中工作:C# 如何扩展对象层次结构以容纳额外数据?,c#,oop,object,C#,Oop,Object,我在一个具有类层次结构的C#代码库中工作: class Animal { Animal prey; } class Mammal : Animal { Mammal[] livesAmicablyWith; } class Lion : Mammal { } 请原谅这个愚蠢的例子 我想重新调整这个类层次结构的用途,使其能够以相同的对象格式表示,但这需要更多的数据。在我的理想世界中,它看起来是这样的: class Animal { Animal prey; string moreAnimalDa
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; }
然而,我希望避免将成员添加到这个现有的层次结构中,因为它们充其量只是浪费空间,最坏的情况是容易引起bug的干扰
此外,我需要所有的原始功能,以继续工作!以下是我的想法:
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 { }
这里有什么建议吗?我想这取决于您希望附加数据的“标准”程度。您可以简单地使用更多多态性来实现以下结果:
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
{
字符串GetMoreData();
}
扩展类动物:动物,扩展数据
{
公共虚拟字符串GetMoreData()
{
if(类型(T)=类型(动物))
返回“额外动物数据”;
返回字符串。空;
}
}
扩展类哺乳动物:哺乳动物,Iextendedata
{
公共重写字符串GetMoreData()
{
if(类型(T)=类型(哺乳动物))
返回“额外哺乳动物数据”;
返回base.GetMoreData();
}
}
扩展类Lion:Lion,iextendedata
{
公共重写字符串GetMoreData()
{
如果(类型(T)=类型(狮子))
返回“额外数据”;
返回base.GetMoreData();
}
}
在使用中,您可以动态强制转换到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>();
}
var哺乳动物=getLion();//返回一个lion…可能是扩展lion,但可能不是
var extended=哺乳动物,如IExtendedData;
if(扩展!=null)
{
string=extended.GetMoreData();
字符串lionData=extended.GetMoreData();
}
从本质上讲,您试图处理的是多重继承,这当然不能在C#中实现(请参阅Stackoverflow上的大量Q)
你的选择包括:-
移动到接口:IAnimal
、IMammal
、ILion
,并在引用这些项时停止使用类。现在可以创建丑陋的大组合类,但只能使用IAnimal
或IAnimalExtended
引用它,以便只有相关属性可见。更好地使用将不同逻辑特性分组的接口;可能是ISocial
而不是IAnimalExtended
其中ISocial
定义了生物如何相互作用
使用组合而不是继承:lionextend
将公开喂养
和社会性
的属性,这些属性不是在一些基本动物
类中实现的,而是在处理一个问题的较小类中实现的
两者兼顾:使用接口,喜欢组合而不是继承。我认为您选择的方法是合理的,并且会起作用。我会尝试在添加值时(假设以某种方式封装)而不是在使用值时进行类型检查(例如,添加到livesAmicablywith的哺乳动物)。它将使错误更容易捕获。我认为这是一个很好的模式用例。你想的解决方案肯定是朝着这个方向的。你在
if
行中缺少了一个括号。从我嘴里说出了这些话。@hunter:这是什么评论?这不是一个特别复杂的解决方案…它明确地解决了他不修改现有类层次结构的愿望,并且仍然允许他以一种相当不可知的方式(因此是泛型)选择获取扩展数据的类型。检查一下你在门口的态度…否则你在这里不会得到太多尊重。好的,伙计们,把它降低一个等级,否则国防部就得锁定一根柱子。还有,jrista,我嘲笑你的代言人。你的代言人就像你的颈胡子一样瘦小。代表不会让你成为比任何人都好的人。除了Jon Skeet,他真的比其他人都好。@Will:如果你真的是Skeet,随着他的代表和我的代表之间的距离不断增加,代表的评论将以指数增长的曲线同时变得有趣和可怕;P