C# 创建“派生类”类型的对象

C# 创建“派生类”类型的对象,c#,inheritance,derived-class,C#,Inheritance,Derived Class,我最近一直在研究类继承,我不断遇到这段特定的代码 public class Foo { public bool DoSomething() { return false; } } public class Bar : Foo { public new bool DoSomething() { return true; } } public cass Test { public static void Main ()

我最近一直在研究类继承,我不断遇到这段特定的代码

public class Foo {      

 public bool DoSomething() 
 { 
   return false; 
 } 
}  

public class Bar : Foo { 

 public new bool DoSomething() 
 { 
   return true; 
 } 
}  

 public cass Test { 

  public static void Main () {   

    Foo test = new Bar (); 

    Console.WriteLine (test.DoSomething ());     
  } 
} 
这里让我困惑的是,如果是我,我会按类型Bar创建一个Bar实例

Bar test = new Bar();

我不明白为什么会按照代码中的方式创建它。

通常不会。一个更现实的例子是

void DoSomethingWithAFoo(Foo f) {
    f.DoSomething();
}

在这种情况下,f可以是一个Foo或一个Bar,DoSomethingWithAFoo不需要知道或关心。

一般来说,它不会。一个更现实的例子是

void DoSomethingWithAFoo(Foo f) {
    f.DoSomething();
}

在这种情况下,f可以是一个Foo或一个Bar,DoSomethingWithAFoo不需要知道或关心。

Bar源于Foo,因此创建一个Bar实例并分配给一个Foo引用是完全有效的。我怀疑您所展示的示例代码仅仅表明Bar是一个Foo,因此是可赋值的。

Bar源于Foo,因此创建Bar实例并将其赋值给Foo引用是完全有效的。我怀疑您所展示的示例代码仅仅表明Bar是一个Foo,因此是可赋值的。

在现实世界的对象中更容易想到这些东西

试着想想一辆车。您可以拥有不同品牌/型号的汽车,但每辆汽车的基本功能相同

您的代码可以以同样的方式处理对象。您编写的代码适用于任何汽车,但您确实可以指定您想要的任何品牌/型号的汽车:

public class Car
{
    public virtual void Drive()
    {
    }
}

public class ChevyVolt : Car
{
    public override void Drive()
    {
        // Initialize the battery and go
    }
}

public class CadillacEscalade : Car
{
    public override void Drive()
    {
        // Check to ensure you have an oil field worth of gas and go
    }
}
现在,使用这些定义…您可以创建一个负责驾驶汽车的类。什么车都行。你只需要担心驾驶:

public class Commuter
{
    public void GoToWork()
    {
        // Garage.PickCar() could return either ChevyVolt or an Escalade
        Car todaysRide = Garage.PickCar();

        // Now that we have a car, go to work
        todaysRide.Drive();
    }
}

在现实世界的对象中更容易想到这些东西

试着想想一辆车。您可以拥有不同品牌/型号的汽车,但每辆汽车的基本功能相同

您的代码可以以同样的方式处理对象。您编写的代码适用于任何汽车,但您确实可以指定您想要的任何品牌/型号的汽车:

public class Car
{
    public virtual void Drive()
    {
    }
}

public class ChevyVolt : Car
{
    public override void Drive()
    {
        // Initialize the battery and go
    }
}

public class CadillacEscalade : Car
{
    public override void Drive()
    {
        // Check to ensure you have an oil field worth of gas and go
    }
}
现在,使用这些定义…您可以创建一个负责驾驶汽车的类。什么车都行。你只需要担心驾驶:

public class Commuter
{
    public void GoToWork()
    {
        // Garage.PickCar() could return either ChevyVolt or an Escalade
        Car todaysRide = Garage.PickCar();

        // Now that we have a car, go to work
        todaysRide.Drive();
    }
}

编写此代码可能是为了演示重写和隐藏基类方法之间的区别:

在这种情况下,使用Foo变量实例化Bar对象将使用基类方法DoSomething并输出false。如果DoSomething方法在基类中声明为virtual,并在派生类中重写,则输出将为true,如下例所示:

public class Foo {      

 public virtual bool DoSomething() 
 { 
   return false; 
 } 
}  

public class Bar : Foo { 

 public override bool DoSomething() 
 { 
   return true; 
 } 
} 

编写此代码可能是为了演示重写和隐藏基类方法之间的区别:

在这种情况下,使用Foo变量实例化Bar对象将使用基类方法DoSomething并输出false。如果DoSomething方法在基类中声明为virtual,并在派生类中重写,则输出将为true,如下例所示:

public class Foo {      

 public virtual bool DoSomething() 
 { 
   return false; 
 } 
}  

public class Bar : Foo { 

 public override bool DoSomething() 
 { 
   return true; 
 } 
} 

您可以分配一个更通用的Foo和一个不太通用的Boo类型,这通常是在利用多态性时完成的。经典的例子是使用Animal、Dod和Cat,然后你可以说Animal=newdog或Animal=newcat,然后你可以调用它的虚拟函数,并自动调用适当的函数。这不是您的情况,因为您正在将函数DoSomething与new…重叠。

您可以分配一个更通用的Foo和一个不太通用的Boo类型。这通常是在利用多态性时完成的。经典的例子是使用Animal、Dod和Cat,然后你可以说Animal=newdog或Animal=newcat,然后你可以调用它的虚拟函数,并自动调用适当的函数。这不是你的情况,因为你把函数与新的函数重叠了…

如果你认为它只想实现由FoO所定义的功能,它可能会更有意义。Bar可以自由添加与任何Bar相关的更多功能


现在,调用代码只关心FO定义的抽象,因此,尽管事实上您正在创建BAR,但是您只得到FoO定义的契约,而不是BAR.ISFALID函数。这可能更有意义。Bar可以自由添加与任何Bar相关的更多功能


现在调用代码只关心Foo定义的抽象,因此,尽管您正在创建Bar,但您只得到Foo定义的契约,因此不是Bar。我刚刚定义的是有效的功能。

我知道代码的用途,但我不明白的是,在创建子类的实例时,如何使用超类作为引用。如果超类方法是虚拟的,真的有什么好处吗?如果超类方法是虚拟的,会有什么不同吗?大多数其他答案都会深入讨论使用基类和/或接口inst的好处
具体类的ead—归根结底,您希望依赖于抽象而不是具体的东西,以便以后更改实际实现—这是多态性的基础,并使IoC/Dependency注入等功能更加强大我知道代码的目的,但我不明白的是,在创建子类的实例时,如何使用超类作为引用。如果超类方法是虚拟的,那么它真的有什么好处吗?如果超类方法是虚拟的,那么会有什么不同吗?大多数其他答案都会深入讨论使用基类和/或接口而不是具体类的好处-归结起来,您希望依赖于抽象而不是具体的东西,以便以后可以更改实际的实现on-这是多态性的基础,使IoC/依赖性注入等功能更加强大。您寻求的答案位于BrokenGlass的答案和Justin的答案与多态性的混合中。不幸的是,这种语义没有简单的答案。您需要熟悉工厂模式、IoC或依赖注入。工厂模式可能是最简单的模式。没有经验,你需要一本书来分解复杂的细节。头先设计模式是一个很好的选择。你要寻找的答案是BrokenGlass的答案和Justin的答案混合在一起的多态性。不幸的是,这种语义没有简单的答案。您需要熟悉工厂模式、IoC或依赖注入。工厂模式可能是最简单的模式。没有经验,你需要一本书来分解复杂的细节。头先设计模式是一个很好的选择。