实现抽象方法时更改参数类型

有没有办法在抽象方法中将抽象类型定义为参数,并且当在派生类中实现该方法时,您是否更改方法的类型以接受派生类型?

码:

public abstract class ProductBase { } public class SomeProduct : ProductBase { } public abstract class A { protected abstract void addProduct(ProductBase p); } // This works public class B : A { protected override void addProduct(ProductBase p) { // Do some work } } // This is what I'd like to do public class C : A { // Compiler error here because I have accepted a SomeProduct and not a ProductBase protected override void addProduct(SomeProduct p) { // Do some work on the specialisation - I can use the SomeProduct directly } } 

在我的脑海中,它有一些道理。 一个抽象类,指示派生类必须实现的方法,但它们可以更改作为参数传入的对象的类型,只要它来自同一个inheritance链…

我最终做的是从抽象类中删除抽象方法AddProduct ,而不是仅在派生类中实现它,但是将来没有其他类的合同,他们必须创建自己的AddProduct实现。 它感觉不对

我希望这是有道理的。 抱歉,如果这是一个重复的问题,但我找不到任何搜索。

谢谢,
bgs264

您可以将A类设为generics,并在addProduct方法中使用generic参数:

 public abstract class A where TProduct : ProductBase { protected abstract void addProduct(TProduct p); } public class B : A { protected override void addProduct(ProductBase p) { } } public class C : A { protected override void addProduct(SomeProduct p) { } } 

坦率地说,对于实现代码,我只是和演员一起生活。 我唯一能让这个“漂亮”的是它是否会影响公众来电者:

 protected override void addProduct(ProductBase p) { SomeProduct prod = (SomeProduct)p; // ... } 

喜欢自己的一个选择是generics:

 public abstract class A where T : ProductBase { protected abstract void addProduct(T p); } public class C : A { protected override void addProduct(SomeProduct p) { // ... } } 

我不喜欢这个的原因是你不能再使用非genericsA了,所以你失去了很多抽象。 另一种选择是重新声明参数的方法。 不幸的是,你不能在同一级别newoverride ,但解决方法是使用2种方法:

 public abstract class A { protected void addProduct(ProductBase p) { addProductImpl(p);} protected abstract void addProductImpl(ProductBase p); } public class C : A { new protected void addProduct(SomeProduct p) { addProductImpl(p);} protected override void addProductImpl(ProductBase p) { SomeProduct prod = (SomeProduct) p; // ... } } 

不,这是不可能的:假设您在类A的变量上调用addProduct ,该变量指向类C的实例,传递一个对象是ProductBase ,但不是SomeProduct 。 传递的实例无法转换为SomeProduct ,这就是为什么它不会首先编译。

最接近这一点的是具有generics的解决方案:

 public abstract class A where T : ProductBase { protected abstract void addProduct(T p); } 

然后,您可以像这样定义C类:

 public class C : A { protected override void addProduct(SomeProduct p); } 

当然,这意味着您必须键入任何类型A变量到SomeProduct ,如A = new C();

在不指定T类型参数的实际值的情况下,您不能再拥有类型A的变量(提供addProduct方法)。 另一方面,如上所述,在您的解决方案中也不可能调用addProduct方法。

您现在可能会引入一种非强类型方法:

 public abstract class A where T : ProductBase { protected abstract void addProduct(T p); protected void addProductUntyped(ProductBase p) { T typedProduct = p as ProductBase; if (typedProduct != null) { addProduct(typedProduct); } else { throw new ArgumentException("p has an incompatible type."); } } } 

但是,当类中的某些用户可以知道generics类型而其他用户不知道时,通常只需要这样的解决方案。