为什么调用我的派生类中的方法调用基类方法? [英] Why does calling a method in my derived class call the base class method?
问题描述
请考虑这段代码:
class Program
{
static void Main(string [] args )
{
人=新教师();
person.ShowInfo();
Console.ReadLine();
}
}
public class Person
{
public void ShowInfo()
{
Console.WriteLine am Person);
}
}
public class Teacher:Person
{
public new void ShowInfo()
{
Console.WriteLine老师);
}
}
当我运行此代码时,会输出以下内容:
我是人
你可以看到它是一个实例,如果教师
,而不是人
。为什么代码这样做?
new
和 virtual
/ override
。
你可以想象,一个类,当被实例化时,只不过是一个指针表,指向它的方法的实际实现。以下图片应该可以很好地显示:
现在有不同的方法,一个方法可以定义。当它与继承一起使用时,每个行为都不同。标准的方式总是工作像上面的图像说明。如果您想更改此行为,可以在方法中附加不同的关键字。
1。抽象类
第一个类是 abstract
。 abstract
方法指向无处:
如果你的类包含抽象成员,它也需要标记为 abstract
,否则编译器不会编译您的应用程序。您不能创建抽象
类的实例,但是您可以从它们继承并创建继承的类的实例,并使用基类定义访问它们。在你的例子中,这将是:
public abstract class Person
{
public abstract void ShowInfo );
}
public class教师:人
{
public override void ShowInfo()
{
Console.WriteLine(I am a老师!);
}
}
public class Student:Person
{
public override void ShowInfo()
{
Console.WriteLine (我是学生!);
}
}
如果调用, code> s和 那么,当你从 第二种方法是使用 关键的区别是, c $ c> Person.ShowInfo
不再指向 nowhere 。这也是为什么你可以创建
Person person = new Teacher(); ShowInfo
person.ShowInfo(); //显示我是老师!
person = new Student();
person.ShowInfo(); //显示我是学生!
教师
是 Person
s,但是当他们被要求提示信息时,关于自己。但是,要求他们提示他们的信息的方法是一样的:使用 Person
类接口。
Person
继承时,幕后发生了什么?当实现 ShowInfo
时,指针不再指向 nowhere ,它现在指向实际的实现!创建学生
实例时,它指向学生
s ShowInfo
:
2。虚方法
virtual
方法。除非您在基类中提供了一个可选默认实现,所以行为是一样的。类可以使用 virtual
成员,但是继承的类可以提供不同的实现。这是你的代码实际上应该工作:
public class Person
{
public virtual void ShowInfo()
{
Console.WriteLine(I am a person!);
}
}
public class教师:人
{
public override void ShowInfo()
{
Console.WriteLine (我是老师!);
}
}
Person
的实例(因此不需要标记为 abstract
任何更长):
你应该注意到,现在看起来和第一个图像不一样。这是因为 virtual
方法指向一个实现标准方式。使用 virtual
,您可以告诉 Persons
,他们可以 )为 ShowInfo
提供了不同的实现。如果你提供了一个不同的实现(使用 override
),就像我上面的 Teacher
与 abstract
相同。想象一下,我们没有为学生
s提供自定义实现:
public class Student:Person
{
}
这:
人员=新教师
person.ShowInfo(); //显示我是老师!
person = new Student();
person.ShowInfo(); //显示我是个人!
以及学生的图片
将如下所示:
3。神奇的`new`关键字akaShadowing
新的
您可以在通用类中提供与基类/接口中的方法具有相同名称的方法。两者都指向自己的自定义实现:
执行way around。实现类似于您提供的实现。根据您访问方法的方式,行为不同:
教师教师=新教师
人=(人)教师;
teacher.ShowInfo(); // Prints'我是老师!'
person.ShowInfo(); // Prints'I am a person!'
这种行为可能是想要的,但在你的情况下是误导。
我希望这可以使您更清楚地了解您!
Consider this code:
class Program
{
static void Main(string[] args)
{
Person person = new Teacher();
person.ShowInfo();
Console.ReadLine();
}
}
public class Person
{
public void ShowInfo()
{
Console.WriteLine("I am Person");
}
}
public class Teacher : Person
{
public new void ShowInfo()
{
Console.WriteLine("I am Teacher");
}
}
When I run this code, the following is outputted:
I am Person
However, you can see that it is an instance if Teacher
, not of Person
. Why does the code do that?
There's a difference between new
and virtual
/override
.
You can imagine, that a class, when instantiated, is nothing more than a table of pointers, pointing to the actual implementation of its methods. The following image should visualize this pretty well:
Now there are different ways, a method can be defined. Each behaves different when it is used with inheritance. The standard way always works like the image above illustrates. If you want to change this behavior, you can attach different keywords to your method.
1. Abstract classes
The first one is abstract
. abstract
methods simply point to nowhere:
If your class contains abstract members, it also needs to be marked as abstract
, otherwise the compiler will not compile your application. You cannot create instances of abstract
classes, but you can inherit from them and create instances of your inherited classes and access them using the base class definition. In your example this would look like:
public abstract class Person
{
public abstract void ShowInfo();
}
public class Teacher : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a teacher!");
}
}
public class Student : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a student!");
}
}
If called, the behavior of ShowInfo
varies, based on the implementation:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a student!'
Both, Student
s and Teacher
s are Person
s, but they behave different when they are asked to prompt information about themselves. However, the way to ask them to prompt their information, is the same: Using the Person
class interface.
So what happens behind the scenes, when you inherit from Person
? When implementing ShowInfo
, the pointer is not pointing to nowhere any longer, it now points to the actual implementation! When creating a Student
instance, it points to Student
s ShowInfo
:
2. Virtual methods
The second way is to use virtual
methods. The behavior is the same, except you are providing an optional default implementation in your base class. Classes with virtual
members can be instanciated, however inherited classes can provide different implementations. Here's what your code should actually look like to work:
public class Person
{
public virtual void ShowInfo()
{
Console.WriteLine("I am a person!");
}
}
public class Teacher : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a teacher!");
}
}
The key difference is, that the base member Person.ShowInfo
isn't pointing to nowhere any longer. This is also the reason, why you can create instances of Person
(and thus it does not need to be marked as abstract
any longer):
You should notice, that this doesn't look different from the first image for now. This is because the virtual
method is pointing to an implementation "the standard way". Using virtual
, you can tell Persons
, that they can (not must) provide a different implementation for ShowInfo
. If you provide a different implementation (using override
), like I did for the Teacher
above, the image would look the same as for abstract
. Imagine, we did not provide a custom implementation for Student
s:
public class Student : Person
{
}
The code would be called like this:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a person!'
And the image for Student
would look like this:
3. The magic `new` keyword aka "Shadowing"
new
is more a hack around this. You can provide methods in generalized classes, that have the same names as methods in the base class/interface. Both point to their own, custom implementation:
The implementation looks like the one, you provided. The behavior differs, based on the way you access the method:
Teacher teacher = new Teacher();
Person person = (Person)teacher;
teacher.ShowInfo(); // Prints 'I am a teacher!'
person.ShowInfo(); // Prints 'I am a person!'
This behavior can be wanted, but in your case it is misleading.
I hope this makes things clearer to understand for you!
这篇关于为什么调用我的派生类中的方法调用基类方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!