如何在继承抽象类时同时添加新成员并重写抽象成员?
解决方案说明
首先要明确:在C#里,直接用抽象类的抽象成员来实现你想要的效果是行不通的——因为派生类必须重写抽象成员,而如果同时定义一个同名但返回类型不同的new成员,编译器会报错(方法/属性的签名不包含返回类型,这属于重复定义)。
不过我们有两种可行的变通方案,取决于你是否能调整抽象类的设计:
方案1:把抽象类的成员改为虚拟成员(基类仍为抽象类)
如果可以把抽象类里的Member从抽象改为虚拟(即使基类是抽象类,也允许包含虚拟成员),那就能轻松实现需求:
abstract class AFoo { // 把抽象成员改为虚拟成员,可提供默认实现(或留空,按需调整) public virtual string Member { get; } } class Foo : AFoo { // 用new关键字隐藏基类的string类型Member public new int Member { get; } = 123; // 可选:如果需要自定义基类虚拟成员的行为,也可以重写它 // public override string Member { get; } = "Hello from base"; }
使用效果完全符合你的预期:
var foo = new Foo(); AFoo afoo = foo; Console.WriteLine(foo.Member); // 输出int类型的123 Console.WriteLine(afoo.Member); // 输出string类型的默认值(或你重写的内容)
方案2:借助接口实现类内显式分离(保留抽象类的抽象成员)
如果你必须保留抽象类的抽象成员,那可以引入一个接口来分离两种类型的Member,通过显式接口实现来规避命名冲突:
// 定义接口承载string类型的Member interface IStringMember { string Member { get; } } abstract class AFoo : IStringMember { // 抽象类实现接口,把具体逻辑委托给抽象成员 string IStringMember.Member => GetStringMember(); protected abstract string GetStringMember(); } class Foo : AFoo { // 派生类对外暴露int类型的Member public int Member { get; } = 123; // 实现抽象类要求的抽象方法 protected override string GetStringMember() { return "Hello from string member"; } }
使用时只需做一次接口转换就能获取string类型的成员:
var foo = new Foo(); AFoo afoo = foo; Console.WriteLine(foo.Member); // 输出int类型的123 Console.WriteLine(((IStringMember)afoo).Member); // 输出string类型的内容
这个方案虽然需要显式转换,但能严格保留抽象类的抽象成员设计,同时实现你想要的访问逻辑。
总结一下:如果能调整抽象类的成员为虚拟类型,方案1最直接;如果必须保留抽象成员,方案2是可行的替代方案。
内容的提问来源于stack exchange,提问作者greenoldman
相关产品推荐
相关产品推荐

