我正在尝试设置一些类:
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;
}
}
}
显然,这不是我想要完成的,但这个想法是:
存在那些AnimalDefaultClass衍生物,因为每个Animal类都有不同的属性,但根据定义,总会有一个类能够为任何Animal获取这些值。
我的问题是:
即使MammalDefaultClass继承自AnimalDefaultClass
,也不会将重写版本的CopyFrom(MammalDefaultClass)识别为抽象CopyFrom(AnimalDefaultClass)的有效覆盖。是否可以将基类指定为抽象成员的参数?有一个简单的*解决方法吗?或者整个事情是错误的?
-edit:我的决议 - 在玩了一些MWB和sza的建议后,我最终让每个子类使用base参数实现该方法,然后根据需要转换输入,如:
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),这是将抽象方法放在基类中的重点。
答案 0 :(得分: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");
答案 1 :(得分:1)
事实证明,即使MammalDefaultClass是AnimalDefaultClass的子类,也不能覆盖使用AnimalDefaultClass并使用MammalDefaultClass的函数。
考虑这段代码:
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中的行为)。