如何扩展对象层次结构以保存额外数据?

时间:2010-07-27 00:09:31

标签: c# oop object

我正在使用具有类层次结构的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 {  }

这里有什么建议吗?

4 个答案:

答案 0 :(得分:1)

基本上你要处理的是多重继承,当然你不能在C#中做到(关于那个,请参阅Stackoverflow上的很多问题)。

您的选择包括: -

移至界面IAnimalIMammalILion并在引用这些项目时停止使用类。您现在可以创建丑陋的大型组合类,但只能使用IAnimalIAnimalExtended来引用它,以便只显示相关属性。甚至可以更好地使用分组不同逻辑特征的接口也许ISocial代替IAnimalExtended,其中ISocial定义了生物彼此之间的互动方式。

使用合成而不是继承LionExtended会公开FeedingSocialNature的属性,这些属性不是在某个基础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模式的一个很好的用例。您正在考虑的解决方案当然是朝这个方向发展的。

相关问题