关于从继承的类实例化一个类
本文关键字:一个 实例化 继承 | 更新日期: 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();