1

我正在尝试设置一些类,例如:

public abstract class AnimalBase {      
  public string SpeciesName { get; private set; }

  public AnimalBase(string speciesName) {
    this.SpeciesName = speciesName;
  }

  public abstract void CopyFrom(AnimalDefaultClass defaultVals);
}

public class Mammal : AnimalBase {
  public bool WalksUpright { get; private set; }

  public Mammal(string speciesName) : base(speciesName) {
    this.CopyFrom(new MammalDefaultClass(speciesName));
  }

  public override void CopyFrom(MammalDefaultClass defaultVals) {
    this.WalksUpright = defaultVals.WalksUpright;
  }

  public void Cripple() {
    this.WalksUpright = false;
  }
}

public class MammalDefaultClass : AnimalDefaultClass {
  public bool WalksUpright { get; private set; }

  public MammalDefaultClass(string speciesName) {
    using (var dataStore = theoreticalFactory.GetDataStore()) {
      this.WalksUpright = dataStore[speciesName].WalksUpright;
    }
  } 
}

显然这不是我想要完成的,但这个想法是:

  • 从抽象基础(动物)继承的几个类(哺乳动物、鱼类、昆虫等)。
  • 每个子类都有一个对应的类,它可以使用(在这种情况下填充可变的默认值)作为在基类中定义为抽象的方法的参数。
  • 每个相应的类(MammalDefaultClass、FishDefaultClass、InsectDefaultClass 等)都继承自一个公共基类(AnimalDefaultClass)。

存在这些 AnimalDefaultClass 派生类是因为每个 Animal 类都有不同的属性,但根据定义,总会有一个类能够为任何 Animal 获取这些值。

我的问题是:

即使 MammalDefaultClass 继承自 AnimalDefaultClass,CopyFrom(MammalDefaultClass) 的覆盖版本也不会被识别为抽象 CopyFrom(AnimalDefaultClass) 的有效覆盖

是否可以将基类指定为抽象成员的参数?有一个简单的*解决方法吗?还是这整件事只是布置错了?

-编辑:我的解决方案- 在玩弄了一些 MWB 和 sza 的建议之后,我最终让每个子类使用基本参数实现该方法,然后适当地转换输入,例如:

public class Mammal : AnimalBase {
  ...

  // implements the abstract method from the base class:
  public override void CopyFrom(AnimalDefaultClass defaultVals) {
    this.CopyFrom((MammalDefaultClass)defaultVals);
  }

  public void CopyFrom(MammalDefaultClass defaultVals) {
    this.WalksUpright = defaultVals.WalksUpright;
  }
}

该解决方案迫使我始终实现 CopyFrom(AnimalDefaultClass) ,这是首先将抽象方法放在基类中的重点。

4

2 回答 2

2

我认为您可以尝试抽象工厂模式。基本上,您希望在创建对象期间处理一些构造逻辑,并且对于Product的每个不同子类型,您可以做不同的事情。

public abstract class AnimalBase
{
    public string SpeciesName { get; private set; }

    protected AnimalBase(string speciesName)
    {
        this.SpeciesName = speciesName;
    }
}

public class Mammal : AnimalBase
{
    public bool WalksUpright { get; set; }

    public Mammal(string speciesName) : base(speciesName)
    {
    }

    public void Cripple()
    {
        this.WalksUpright = false;
    }
}

public interface IAnimalFactory<T> where T : AnimalBase
{
    T CreateAnAnimal(string speciesName);
}

public class MammalFactory: IAnimalFactory<Mammal>
{
    public Mammal CreateAnAnimal(string speciesName)
    {
        var mammal = new Mammal(speciesName);
        var mammalDefault = new MammalDefaultClass(speciesName);
        mammal.WalksUpright = mammalDefault.WalksUpright;
        return mammal;
    }
}

当你想创建一个子类型的对象时,你可以做例如

var mammalFactory = new MammalFactory();
var bunny = mammalFactory.CreateAnAnimal("Bunny");
于 2013-07-29T16:43:18.367 回答
1

因此事实证明,即使 MammalDefaultClass 是 AnimalDefaultClass 的子类,您也不能用采用 MammalDefaultClass 的函数覆盖采用 AnimalDefaultClass 的函数。

考虑这个代码块:

public class Dinosaur : AnimalDefaultClass;
Dinosaur defaultDinosaur;

public void makeDinosaur(AnimalDefaultClass adc)
{
    adc.CopyFrom(defaultDinosaur);
}

MammalDefaultClass m;
makeDinosaur(m);

在这种情况下,MammalDefaultClass 是 AnimalDefaultClass 的子类,因此 m 可以作为 adc 传递给 makeDinosaur。此外,AnimalDefaultClass 的 CopyFrom 只需要另一个 AnimalDefault 类,因此我可以传入恐龙。但是那个类实际上是一个哺乳动物,所以需要一个 MammalDefaultClass,而恐龙不是。

解决方法是采用原始类型签名并在参数类型错误时抛出错误(类似于数组在 Java 中的行为方式)。

于 2013-07-29T16:33:40.947 回答