繁体   English   中英

如何将Base对象的引用更改为Derived,并将其作为Derived类型进行实例化

[英]How to change reference of Base object to Derived which was instatiated as Derived type

为什么我无法从Derived访问M3方法? Intellisense仅显示基类中的M1和M2。 如何将bc的参考从Base类型更改为Refernce Type,以便我可以访问M3方法。

class Program
{
    static void Main(string[] args)
    {
        Base bc = new Derived();
        bc.M3():// error
    }
}

class Base
{
    public void M1()
    {
        Console.WriteLine("M1 from BASE.");
    }
    public void M2()
    {
        Console.WriteLine("M2 from BASE.");
    }
}

class Derived : Base
{
    public void M3()
    {
        Console.WriteLine("M3 from DERIVED.");
    }
}

编译器必须在编译时解析名称M3 这是在Base类型的引用上调用的, Base没有该名称的成员。 事实上它恰好指向运行时的Derived实例,因为编译器正在查看编译时可用的信息。

是的,在这种特定情况下,编译器可以看到bc始终初始化为Derived值,因此它应该在那里看。 然而,这不是c#编译器的工作原理。 它仅查看所涉及引用的编译时类型

因为您将您的类型转换为基类,所以所有可用成员的集合将减少为Base可用的成员集。

Derived bc = new Derived();
bc.M3():// CORRECT

或者干脆

var bc = new Derived();
bc.M3():// CORRECT

如果您需要在应用程序中使用Base class for polymorphism并且需要使用M3()考虑在Base类中移动它

因为bc引用唯一的保证是它将引用Base的实例或从Base派生的东西。

考虑代码是否改变如下:

Base bc = new Derived();
if(DateTime.DayOfWeek == DayOfWeek.Sunday)
{
  bc = new Base();
}
bc.M3();

这是完全合法的,因为bc的保证仍然是满满的。

有两种方法可以解决这个问题:转换和多态。

转换意味着您告诉编译器您知道这确实是Derived实例,即使引用是Base类型。

Base bc = new Derived();
if(bc is Derived)
{
  ((Derived)bc).M3();
}

另一种是在基类中声明M3函数,然后在派生类中重写它

class Base
{
   // Other stuff...

   public virtual void M3()
   {
   }
}

class Derived : Base
{
    public override void M3()
    {
        Console.WriteLine("M3 from DERIVED.");
    }
}

正如其他人所说, bc被宣布为Base类型。 你需要先抛出它

    Base bc = new Derived();
    ((Derived)bc).M3()

如果bc实际上是Base类型而不是Derived那么这将是一个运行时错误。

这是因为编译器只看到您正在使用Base类型的变量。

请使用以下代码:

Base bc = null;

if (SomeValue)
{
    bc = new Base();
}
else
{
   bc = new Derived();
}

SomeValue的值可以在运行时变化。 这意味着编译器在编译时不会知道bc的实际类型。 这是基类的全部概念。 您与基类共享相同的接口,但您可以更改方法的实现。

但是,您可以将类型转换为其他类型:

Derived dc = bc as Derived;

if ( dc != null ) // cast succeeded so we have a Derived
{
    dc.M3();
}

要只检查一个类型是另一种类型的可以使用的isif (dc is Derived)

但请注意这样做的危险。 这样,您就会使用所有类型特定的检查来乱丢代码,这使得它更难理解和维护。 如果您想了解更多有关此内容的信息,请阅读S OLID模式

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM