Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何扩展对象层次结构以容纳额外数据?_C#_Oop_Object - Fatal编程技术网

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

我在一个具有类层次结构的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; }
然而,我希望避免将成员添加到这个现有的层次结构中,因为它们充其量只是浪费空间,最坏的情况是容易引起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