通过由基类实现的接口调用类的方法 c#

3

我有这段代码,但我就是理解不了它。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1 {
    interface IStoreable {
        void Read();
        void Write();
    }
    class Person : IStoreable {
        public virtual void Read() { Console.WriteLine("Person.Read()"); }
        public void Write() { Console.WriteLine("Person.Write()"); }
    }
    class Student : Person {
        public override void Read() { Console.WriteLine("Student.Read()"); }
        public new void Write() { Console.WriteLine("Student.Write()"); }
    }
    class Demo {
        static void Main(string[] args) {
            Person s1 = new Student();
            IStoreable isStudent1 = s1 as IStoreable;

            // 1
            Console.WriteLine("// 1");
            isStudent1.Read();
            isStudent1.Write();           

            Student s2 = new Student();
            IStoreable isStudent2 = s2 as IStoreable;

            // 2
            Console.WriteLine("// 2");
            isStudent2.Read();
            isStudent2.Write();

            Console.ReadKey();
        }
    }    
}

我原以为无论哪种情况下,Student.Write() 都会被调用,但结果让我感到困惑:

// 1
Student.Read()
Person.Write()
// 2
Student.Read()
Person.Write()

为什么会调用Person.Write()而不是'Student.Write()`呢?

2
覆盖和隐藏是不同的事情。https://dev59.com/_nRC5IYBdhLWcg3wKtr2 - Oded
3个回答

5
new关键字表示您不打算覆盖基类的Write()方法(无论如何都不行,因为PersonWrite()方法没有标记为virtual)。由于通过IStoreable调用它,所以IStoreable接口与Student类没有任何联系。由于Write()未标记为virtual,因此对于此函数,多态性不适用。

那么,当我使用接口类型的引用调用 Write() 时,将执行已在最初实现该接口的类中实现的方法(在本例中为 Person)? - Robotronx
1
是的,因为基类没有将 Write() 方法标记为 virtual,所以它的子类无法 override 它。 - FMM
那么 IStoreable 唯一关联的是基类 Person,并且所有有关调用哪个方法(通过 IStoreable 调用)的结论都是从这个事实中得出的吗?(很抱歉我问了几乎相同的问题,但我想确保我理解正确) - Robotronx

1

作为IStoreable的学生无法看到Student.Write方法,因为它没有从基类Person中重写。为什么它没有被标记为virtual,并且为什么你使用了new关键字隐藏了基类的实现?


这只是当地大学教材中的一个例子。它被借给我,所以我在其中找到了这个例子,但是无法理解它。 - Robotronx
啊,我明白了,这是一个好问题。Oded 对你的问题的评论也是一个很好的参考。 - Jeb

0
将该人的写入方法设置为虚拟的。当您将其标记为new时,它不会作为继承方法运行。当您将该方法标记为虚拟方法时,这意味着您提供了一个实现,并且可以通过子类进行覆盖。抽象方法要求您实现一个方法(只是更多的信息)。
class Person : IStoreable { 
    public virtual void Read() { Console.WriteLine("Person.Read()"); } 
    public virtual void Write() { Console.WriteLine("Person.Write()"); } 
} 
class Student : Person { 
    public override void Read() { Console.WriteLine("Student.Read()"); } 
    public override void Write() { Console.WriteLine("Student.Write()"); } 

当作为修饰符使用时,new关键字会显式地隐藏从基类继承的成员。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接