C# 创建子类的实例是否会创建父类的实例?
我是C#的新手,我想知道,如果我创建一个子类的实例,它会自动创建父类的实例吗 这是我的密码:C# 创建子类的实例是否会创建父类的实例?,c#,.net,C#,.net,我是C#的新手,我想知道,如果我创建一个子类的实例,它会自动创建父类的实例吗 这是我的密码: class Program { public class ParentClass { public ParentClass() { Console.WriteLine("ChildClass uses my Ctor "); } } public class ChildClass : Paren
class Program
{
public class ParentClass
{
public ParentClass()
{
Console.WriteLine("ChildClass uses my Ctor ");
}
}
public class ChildClass : ParentClass
{
public ChildClass()
{
Console.WriteLine("SaySomething");
}
}
public static void Main()
{
ChildClass child = new ChildClass();
}
}
它是否也会自动创建父类的实例
不是一个单独的例子;当谈到继承时,ChildClass
是一个ParentClass
实例
换句话说,这就像:
创建狗时,我们是否也创建动物的实例
我们不创造狗,也不(分别)创造动物;狗就是动物的例子。如果我们创建一只卷毛狗,卷毛狗就是狗,也是动物。不,它不是,但它调用基构造函数(父类的构造函数)。在您的情况下,它是空的,因此对基类构造函数的调用由编译器为您完成:
class Program
{
public class ParentClass
{
public ParentClass()
{
Console.WriteLine("ChildClass drived from me ");
}
}
public class ChildClass : ParentClass
{
public ChildClass() : base() // base() call is voluntary
{
Console.WriteLine("This also use my Ctor");
}
}
public static void Main()
{
ChildClass child = new ChildClass();
}
}
但是,如果基类没有无参数构造函数,则必须调用它
class Program
{
public class ParentClass
{
public ParentClass(string foo)
{
Console.WriteLine("ChildClass drived from me ");
}
}
public class ChildClass : ParentClass
{
public ChildClass() : base("some foo") // base call is obligatory
{
Console.WriteLine("This also use my Ctor");
}
}
public static void Main()
{
ChildClass child = new ChildClass();
}
}
根据定义,当ChildClass
继承表单ParentClass
时,ChildClass
对象也属于ParentClass
如果你的命名更贴近现实生活,那么就更容易理解
class Animal {}
class Cat : Animal {}
var rocky = new Cat();
瞧,洛奇是一只猫,但它也是一种动物。不,它只会创造一个儿童班。你问题的实际答案是 “否”,它是子类的实例,而不是父类的实例 但如果您的问题是:“您是否有一个包含父类所有属性的实例对象”,答案是 “是”,您将拥有中的所有属性和字段 父类复制到子实例中
具体谈论您的代码:
class Program
{
public class ParentClass
{
public ParentClass()
{
Console.WriteLine("ParentClass constructor is called");
}
}
public class ChildClass : ParentClass
{
public ChildClass()
{
Console.WriteLine("ChildClassConstructor is called");
}
}
public static void Main()
{
//will print that the Parent ctor is called, followed by printing that the child ctor is called
ChildClass child = new ChildClass();
//will print that the Parent ctor is called, followed by printing that the child ctor is called
ParentClass childinparentbox = new ChildClass();
//will print that the Parent ctor is called
ParentClass parent = new ParentClass();
//At this point there are 3 object instances in memory
//by the way, this can't be done. Can't store a parent in a child: a parent is-not-a child
ChildClass parentinchildbox = new ParentClass();
}
}
我更改了消息,使其与提出的观点相关:
构造函数只是一种方法,在创建新对象时强制调用它。您可以使用它来设置新对象以供使用,初始化属性等。类在C#中是分层的-所有东西都是某个东西的子类,有时是对象。您的父类是Object的子类,它只是没有说明。您的孩子被声明为父母的孩子
正如其他人所指出的,当您使用new
时,您不会得到多个对象实例,您只会得到一个您要求创建的对象实例。子类总是可以引用/“存储在”声明为父类型的变量中。这是因为事物在Child->Parent的方向上有一个“is-a”关系。狗是动物,猫是动物,动物是物体。他们没有相反的关系。。你不能普遍地说汽车是法拉利,或者某种动物是狗
因此,事情会追溯到层次结构,您可以将猫或狗存储在声明为容纳动物的变量中。动物可能有一个GetNumberOfLegs()方法,用于报告腿的数量。猫和狗各返回4个,猴子返回2个
面向对象编程的一个关键原则是,您可以以通用的方式引用事物;所有动物都有一定数量的腿。如果是动物中存储的猫/狗,则GetNumberOfLegs()返回4,如果是猴子,则返回2。。但是如果你只对腿的数量感兴趣,你不需要特别知道它是猫、狗、猴子。这将在接下来的讲座中详细介绍,所以我不需要在这里深入讨论。我把这个细节作为一个解释,解释为什么我们甚至想要有一个层次结构,有一个动物,创建一只狗,并将它存储在一个类型为Animal的变量中。我们这样做是因为我们经常想用一种通用的方式来指代事物,因为我们不关心细节;我们定义了我们所关心的一般事物,而具体的事物则符合模型。你可以开车;你不需要专门学习如何驾驶福特或雪佛兰-他们的方向盘和踏板在同一个位置/布置。您可以操作通用接口。你不在乎转向是如何实现的——液压、齿轮齿条、转向垂臂——你只在乎当你“像这样”转动方向盘时,汽车会“像那样”转动
回到你问的问题:
因为Child是一个Parent是一个对象,所以当您创建一个新的Child时,您将看到一个打印输出,指示调用了父构造函数,另一个指示调用了子构造函数。这并不意味着已经在计算机内存中创建了两个对象——构造函数是按正向(从根到尖端)顺序调用的,用于层次结构中的所有对象,从Object开始,然后是Parent,然后是Child。这是因为在任何构造函数的代码中,第一件事就是调用相关的父构造函数。构造函数代码中的第一件事是调用它的父级
因此,运行时从子代开始,然后到达父代、祖父母、曾祖父母,一直到祖先的顶端,然后返回,按照从上到下的顺序在每个构造函数中运行其余的代码。这就是为什么看到调用父构造函数的打印输出,然后看到子构造函数
这都是一个相同的对象,是多个方法调用。看到两个打印输出并不是表示内存中有两个对象,而是一个对象和两个方法(两个构造函数方法),它们以递归顺序被调用。i、 从这个类创建的对象实例应该有这个实现逻辑。创建一个类的实例,获取所有逻辑并将其转换为对象的行为。当您从某个类继承时,基本上是将父类的实现逻辑包含在子类的模板中,因此您只需要得到一个扩展的“模板”。当你创造
class Coffee {}
class Cappucino : Coffee {}