关于从继承的类实例化一个类

本文关键字:一个 实例化 继承 | 更新日期: 2023-09-27 17:53:10

DerivedClass classinst = new DerivedClass();

BaseClass classinst = new DerivedClass();

我似乎看不出有什么区别,编译器也没有抱怨,所以我可以互换使用吗?

关于从继承的类实例化一个类

两者之间的唯一区别是,如果您这样做

DerivedClass classinst = new DerivedClass();

编译器 classinst解释为DerivedClass,并允许您使用在派生类而不是基类中声明的所有特定方法/属性等。

另一方面,如果你这样做BaseClass classinst = new DerivedClass();

编译器将classinst解释为BaseClass,并且您将无法访问这些成员。

请注意,对象的实际类型不会改变。无论使用两个声明中的哪一个,对对象的引用都保持不变。唯一改变的是如何解释引用,以及哪些成员可用;

在第二个示例中,您无法访问DrivedClass的方法或属性,因为您的变量定义为BaseClass。即使DrivedClass的实例在后台,您也不能访问特定于该类型的成员。

使用:

BaseClass classinst = new DrivedClass();

你允许自己也这样做:

BaseClass classinst = new DrivedClassOne();
BaseClass classinst = new DrivedClassTwo();

这在一个情况下可能很好,比如你有一个road对象,它包含一个汽车列表。然后,您可以向列表中添加一辆新的Ford或一辆新的Honda,因为它的类型是car,而不是只有Ford或Honda

区别在于"classinst"变量的类型。

尝试以下代码:

string typename = typeof(classinst).ToString();

如果你想使用多态行为-即在基类中定义一个方法,该方法的行为不同取决于它在派生类中的覆盖方式,但不需要派生类的知识,那么你将其分配为基类。

这是典型的面向对象行为——如果你为此目的使用子类,它们几乎总是被称为基类(或者现在更典型的是作为多个相关类实现的接口)。

那么,在第二个版本中,您将无法使用实例访问特定于派生类的属性/方法(除非强制转换为派生类型)。

想象

public class Animal {
  public int NbOfEyes {get;set;}
}
public class Dog : Animal {
  public bool IsPolite {get;set;}
}
Animal dog = new Dog();
dog.IsPolite = false; //you can't do that. dog is an animal, it doesn't know it can be polite.
dog.NbOfEyes = 2;//you can do that, you have access to animal's properties /methods
Dog dog2 = new Dog();
dog2.IsPolite = false; // you can do that.
dog2.NbOfEyes = 4; //you can also do that, you have access to base class's properties / methods.

面向对象编程中最重要的两个原则是继承多态性

Inheritance允许创建一个继承现有类的数据和行为的类。然后子类可以专门化(通常是通过覆盖)超类的行为。

多态性允许子类的行为就像它的超类一样,所以在你的例子中,DerivedClass的实例可以在需要BaseClass实例的任何地方使用。

所以DerivedClass的实例可以被赋值给BaseClass类型的变量(多亏了多态性)。但是,即使分配给BaseClass类型的变量,它的行为也会像DerivedClass的实例一样,因此任何被重写的行为都将自动使用。

的例子:

class BaseClass
{
    public virtual void ShowMe()
    {
        Console.WriteLine("I'm the base class");
    }
}
class DerivedClass : BaseClass
{
    public override void ShowMe() 
    {
        Console.WriteLine("I'm the derived class");
    }
}
// This will print "I'm the base class"
BaseClass baseClass = new BaseClass();
baseClass.ShowMe(); 
// This will print "I'm the derived class"
DerivedClass derivedClass = new DerivedClass();
derivedClass.ShowMe(); 
// This will print "I'm the derived class"
// Reason: even if assigned to a BaseClass variable,
// it's still a DerivedClass instance
BaseClass baseClass2 = new DerivedClass();
baseClass2.ShowMe(); 
// This will generate a compiler error
// Subclasses can behave like superclasses,
// but the opposite is not possible
DerivedClass derivedClass2 = new BaseClass();