为什么调用我的派生类中的方法调用基类方法? [英] Why does calling a method in my derived class call the base class method?

查看:226
本文介绍了为什么调用我的派生类中的方法调用基类方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑这段代码:

  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 (我是学生!);
}
}

如果调用,

  Person person = new Teacher(); ShowInfo  person.ShowInfo(); //显示我是老师!

person = new Student();
person.ShowInfo(); //显示我是学生!

code> s和教师 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 (我是老师!);
}
}

关键的区别是, c $ c> Person.ShowInfo 不再指向 nowhere 。这也是为什么你可以创建 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, Students and Teachers are Persons, 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 Students 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 Students:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆