用作抽象方法的基类';s参数

本文关键字:参数 基类 抽象方法 | 更新日期: 2023-09-27 18:25:32

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

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获取这些值。

我的问题是:

CopyFrom(MammalDefaultClass)的重写版本未被识别为抽象CopyFrom的有效重写(AnimalDefaultClass),即使MammalDefault Class继承自AnimalDefaultClass

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

-edit:我的解决方案-在对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),这是将抽象方法放在基类中的首要目的。

用作抽象方法的基类';s参数

我认为您可以尝试抽象工厂模式。基本上,您希望在创建对象的过程中处理一些构造逻辑,对于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");

因此,即使MammalDefaultClass是AnimalDefaultClass的子类,您也不能用接受MammalDefault的函数覆盖接受AnimalDefault的函数。

考虑一下这个代码块:

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类,所以我可以传入恐龙。但该类实际上是哺乳动物,因此需要一个哺乳动物默认类,而恐龙不是。

解决方法是采用原始类型签名,如果参数是错误的类型(类似于Java中数组的行为),则抛出错误。