首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将基类(继承)功能添加到不受控制的类中

将基类(继承)功能添加到不受控制的类中
EN

Software Engineering用户
提问于 2013-07-26 19:59:48
回答 1查看 11.7K关注 0票数 4

我有一组来自第三方图书馆的课程。这些类使用继承结构来共享逻辑。我想在继承树的中间添加一个抽象层,以便向所有的子实现(具体的)实现添加功能。

下面是第三方库中类的简化示例:

代码语言:javascript
复制
public interface IAnimal
{
    bool IsMammal { get; }
}

public abstract class Animal : IAnimal
{
    public abstract bool IsMammal { get; }
    public string Name { get; set; }
}

public class Cat : Animal
{
    public override bool IsMammal { get { return true; } }
    public void Pur() {}
}

public class Dog : Animal
{
    public override bool IsMammal { get { return true; } }
    public void Fetch() {}
}

public class Snake : Animal
{
    public override bool IsMammal { get { return false; } }
    public void ShedSkin() {}
}

我想添加AnimalWithSuperPower的概念。这些类型的动物应该有一个额外的属性;SuperPower。我希望能够拥有像CatWithSuperPower这样的类,这些类派生自CatAnimalWithSuperPowerAnimal,这样我就可以访问这些类的所有功能。

以下是SuperPower的定义:

代码语言:javascript
复制
public enum SuperPower { Invisibility, SuperStrength, XRayVision }

我的第一个想法是使用多重继承。但是不幸的是,C#不支持多个基类。

代码语言:javascript
复制
private abstract class AnimalWithSuperPower : Animal
{
    public SuperPower SuperPower { get; set; }
}

// doesn't compile because you can't extend 2 classes
private class DogWithSuperPower : AnimalWithSuperPower, Dog {}

我的下一次尝试使用继承、组合和泛型的组合来尝试交付基类的功能。

代码语言:javascript
复制
private abstract class AnimalWithSuperPower<TAnimalType> : Animal where TAnimalType : IAnimal
{
    public SuperPower SuperPower { get; set; }

    protected readonly TAnimalType Animal;

    protected AnimalWithSuperPower()
    {
        Animal = (TAnimalType) Activator.CreateInstance(typeof(TAnimalType));
    }
}

private class SuperCat : AnimalWithSuperPower<Cat>
{
    public override bool IsMammal { get { return Animal.IsMammal; } }
}

private class SuperCatWithPur : AnimalWithSuperPower<Cat>
{
    public override bool IsMammal { get { return Animal.IsMammal; } }

    public void Pur() // needing duplicate pass-through methods/properties like this is painful :(
    {
        Animal.Pur();
    }
}

private static void ExampleUsage()
{
    var invisibleCat = new SuperCat { SuperPower = SuperPower.Invisibility };
    invisibleCat.Pur(); // doesn't compile - can't access Pur() method because doesn't extend Cat

    var xrayCat = new SuperCatWithPur { SuperPower = SuperPower.XRayVision };
    xrayCat.Pur(); // only works because I exposed the method with the EXACT same signature
}

这一解决办法不是很好(海事组织),因为这些原因:

  • SuperCatSuperCatWithPur实际上不是Cat的实例
  • 您希望从Cat中使用的任何方法都需要在容器类中进行镜像。
  • 感觉有点混乱:AnimalWithSuperPower是一个Animal,但它也有一个Animal类型参数

我也尝试过使用扩展方法来完成这个任务,但是它并没有比上面的两次尝试更好:

代码语言:javascript
复制
private abstract class AnimalWithSuperPower : Animal
{
    public SuperPower SuperPower { get; set; }
}

private static AnimalWithSuperPower WithSuperPower(this Animal animal, SuperPower superPower)
{
    var superAnimal = (AnimalWithSuperPower) animal;
    superAnimal.SuperPower = superPower;
    return superAnimal;
}

private static void ExampleUsage()
{
    var dog = new Dog { Name = "Max" };
    var superDog = dog.WithSuperPower(SuperPower.SuperStrength);
    superDog.Fetch(); // doesn't compile - superDog isn't an instance of Dog
}

如果我控制了第三方类,我很可能会在继承树的中间引入一个新类,但我做不到

我的问题:

我如何对AnimalWithSuperPower建模,以便:

  • 实例的类型为Cat (或适当的子类)、AnimalAnimalWithSuperPower
  • 所有方法和属性都是可用的,不需要额外的传递调用。
EN

回答 1

Software Engineering用户

回答已采纳

发布于 2013-07-26 20:45:44

你为什么不直接使用接口呢?

如果您关心共享功能,可以使用扩展方法作为您的伪基类。这并不完全是理想的,但它应该得到你想要做的事情。

与…有关的东西:

代码语言:javascript
复制
public interface IAnimalWithSuperPower {
    public SuperPower power { get; set; }
}

public class SuperCat : Cat, IAnimalWithSuperPower {
    public SuperPower power { get; set; }
    public SuperCat() {
        SuperPower = SuperPower.SuperStrength;
    }
}

public static void UseSuperPower(this IAnimalWithSuperPower animal) {
    animal.power.doSomething();
}
票数 6
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/206205

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档