You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在继承抽象类时同时添加新成员并重写抽象成员?

解决方案说明

首先要明确:在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 21:03:12