这种嵌套的继承关系该如何实现?

340 天前
 GodOfParentheses

B 类继承自 A 类, β类继承自α类. 同时α作为 A 类的字段, β作为 B 类的字段. 现希望 B 实例调用父类方法(该父类方法调用了字段α)时, 能使用自身环境中的β实例而非α实例(因为α对 B 没有意义, 虽然从父类继承, 但完全不使用, 只使用β)

于是考虑将字段α设为 virtual:


public class Alpha
{
    public virtual void printSelf()
    {
    	print("this is alpha");
    }
}

public class Beta: Alpha
{
    public override void printSelf()
    {
    	print("this is beta");
    }
}

public class A
{
    public virtual Alpha alpha
    {
            get => _alpha;
            set => _alpha = value;
    }
    private Alpha _alpha

    public virtual void PrintSelf()
    {
        alpha.printSelf();
    }
}

public class B: A
{
    public override Alpha alpha
    {
            get => _beta;
            set{}
    }
    // public?
    private Beta _beta;
}


public class Main
{
    var b = new B();
    b.PrintSelf();
}
    

请问这样设计合理吗? 另外, 为了访问β实例中的非继承字段, B 类中的β字段必须设为 public, 这样会带来额外的问题吗?

还是说这种需求就是不合理? 已经有点绕晕了现在. 这种"嵌套的继承关系"有没有专业点的称呼?

515 次点击
所在节点    编程
7 条回复
cxe2v
340 天前
printSelf 方法传入一个实例参数,就可以 B 使用β实例,A 使用α实例
GodOfParentheses
340 天前
@cxe2v 这样的话得靠调用者手动传入α或β实例? 但是调用者往往连 a 实例和 b 实例都不区分, 而α/β又是和 A/B 高度绑定的.
cxe2v
339 天前
@GodOfParentheses 调用者为啥不区分这个实例呢,不区分的话,A 跟 B 内部都用β类型就行了
GodOfParentheses
339 天前
@cxe2v 不好意思, 例子写的不对, 请看新的代码. A/B 类存在接口继承, 调用者持有接口实例, 所以不区分 A/B.
我好像有点明白了, 如果把α也放到接口里是不是就等价于现在的效果?
cxe2v
339 天前
接口继承的话,A,B 互不影响,实现 PrintSelf 是 AB 各自在内部实现的,你想怎么写怎么写都可以
GodOfParentheses
339 天前
根据新理解重新写了第三个版本. 需求的核心是: 父子类中字段 X 有着不同的实现, 希望子实例调用继承自父类的方法 Y 时(Y 方法引用 X 字段), 使用 X 字段自己的实现而非父类的实现.
刚开始纠结的字段 X 在父子类中的继承关系其实不重要.
C#的多态机制可以实现这点, 问题是怎么写更好, 不知道 v3 这种写法还能改进不.
GodOfParentheses
338 天前
v5. 我悟了, 这其实就是个 Liskov 和 Open/Close 原则的应用, "继承抽象而不是继承具体". 又是被自己菜哭的一天.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1000369

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX