【问题标题】:c# What's the difference in these child class instances with an abstract base class? [duplicate]c#这些带有抽象基类的子类实例有什么区别? [复制]
【发布时间】:2016-07-08 20:47:33
【问题描述】:

我不知道如何正确表达这个问题,但我似乎在 StackOverflow 上找不到类似的问题

假设我有一个抽象基类A 和一个子类B

显然我可以通过这两行创建子对象

A child = new B();

B child = new B();

而且它们似乎支持相同的方法用法。

有什么区别?

【问题讨论】:

  • B 必然是A。它拥有A 拥有的一切,甚至可能更多。如果您在B 中添加了在A 中未定义的额外方法或属性,如果您将变量视为A,您将无法使用它们。您必须将其转换回 B
  • @GlorinOakenfoot,嗯,有道理。我认为出现这种情况的原因是因为我的子类中目前没有任何额外的公共方法,所以 A 和 B 在技术上支持同一组方法:)
  • @ygongdev 这很典型。子类之间通常变化的是实现而不是接口

标签: c# class inheritance abstract-class


【解决方案1】:

由于B 派生自AB A,因此您可以将B 的实例设置为类型为A 的引用。

也就是说,设置为A 类型引用的B 实例将能够访问A 的成员,但不能从B 访问。这是一个upcast(将引用从更多类型转换为更少类型)。

【讨论】:

    【解决方案2】:

    B 可以做 A 可以做的所有事情,但 B 可以做的更多——在子类中定义的任何内容都可供 B 使用(但不能用于 A)。

    通过将 B 分配给 A 变量,您(暂时)将其删除,现在它只能执行 A 可以执行的操作(直到您将其分配回 B 变量)。

    【讨论】:

    • B 不一定能做得更多——他们也许能做同样的事情。 :)
    • 是的,如果您创建一个没有任何内容的子类。不是很有用,但可能处于临界状态。
    【解决方案3】:

    在第一种情况下,B 实例自动向下转换(如ECMA standard 第 136 页所述)为引用类型A。这意味着可以调用的方法将是那些在A 中找到的方法。请注意,这些可能比B 中发现的要。但是,所有abstract方法都需要B实现。

    例如,让B 被定义为

    class abstract A
    {
        public abstract void Foo();
    }
    
    class B
    {
        public override void Foo() {}
        public void Bar() {}
    }
    

    这里Bar() 方法仅适用于您的第二种情况 - var B = new B ();

    请注意,如果您使用 var 关键字,则表达式例如new B() 将是 B 类型。

    【讨论】:

    • 这正是激发我好奇心的地方。显然如果我这样做var A = new B(); A 也可以访问Bar(),我想这对我来说有点道理
    • 是的,很用心!这是因为var 关键字会干扰右侧表达式的类型,即new B()。此表达式的类型是 B,因此变量 A 的类型将是 B,尽管它的名称。
    • 但是,如果你这样做A a = new B();你会发现Bar()方法不再可用。
    • 哦,但实际上如果我做了 A = new B()(没有 var),我仍然可以访问 Bar()
    • 是的,如果 A 是 B 类型,你可以
    猜你喜欢
    • 2013-09-24
    • 1970-01-01
    • 2010-11-13
    • 2013-02-17
    • 1970-01-01
    • 2019-12-14
    • 2016-06-03
    相关资源
    最近更新 更多