多态性出乎意料的结果

时间:2014-08-27 13:49:20

标签: c# class polymorphism

在我更多地了解多态性的过程中,我构建了一个小测试并且它返回了意想不到的结果。

所以我的想法是用虚拟/覆盖关键字覆盖基类方法,但似乎我不需要那些?

public class Employee 
        {
            public Employee()
            {
                this.firstName = "Terry";
                this.lastName = "Wingfield";
            }

            public string firstName { get; set; }
            public string lastName { get; set; }

            public void writeName()
            {
                Console.WriteLine(this.firstName + " " + this.lastName);
                Console.ReadLine();
            }
        }

        public class PartTimeEmployee : Employee 
        {
            public void writeName() 
            {
                Console.WriteLine("John" + " " + "Doe");
                Console.ReadLine();
            }
        }
        public class FullTimeEmployee : Employee 
        {
            public void writeName()
            {
                Console.WriteLine("Jane" + " " + "Doe");
                Console.ReadLine();
            }
        }

        static void Main(string[] args)
        {
            Employee employee = new Employee();
            PartTimeEmployee partTimeEmployee = new PartTimeEmployee();
            FullTimeEmployee fullTimeEmployee = new FullTimeEmployee();

            employee.writeName();
            partTimeEmployee.writeName();
            fullTimeEmployee.writeName();
        }
    }

使用上面的代码我期待结果如下:

  1. Terry Wignfield
  2. Terry Wingfield
  3. Terry Wingfield
  4. 但是下面的内容写入了控制台:

    1. Terry Wingfield
    2. John Doe
    3. Jane Doe
    4. 我认为后者不起作用,因为它需要ovrride关键字。

      所以问题是为什么我没有适当的关键词看到后面的名字?

      我希望这很清楚,可以阅读。

      此致

4 个答案:

答案 0 :(得分:5)

您展示的代码中没有多态性。

将其更改为:

Employee employee = new Employee();
Employee partTimeEmployee = new PartTimeEmployee();
Employee fullTimeEmployee = new FullTimeEmployee();

您将获得预期的结果。

更新

OOP中“多态”(多种形式)的概念意味着代码处理特定类型(基类或接口)的引用,而这些引用后面可能存在不同类型(后代,实现)的实例。对于“踢入”的多态,必须有继承和虚方法(在接口实现的情况下使用不同的术语,但让我们使用与您的代码示例相关的术语)。您有继承,但没有虚拟方法。对于常规(非虚拟)方法,方法调用在编译时根据调用方法的对象类型进行解析。

代码:

PartTimeEmployee partTimeEmployee = ...;
partTimeEmployee.writeName();

编译器清楚地知道调用哪个方法writeName,它是PartTimeEmployee.writeName。 同样,对于代码:

Employee partTimeEmployee = ...;
partTimeEmployee.writeName();

要调用的方法是Employee.writeName

答案 1 :(得分:4)

这称为方法隐藏。您只是在派生类中隐藏基类方法。您应该收到警告,但这完全合法。有关更多信息,请参阅documentation。您可能还想查看this问题

答案 2 :(得分:0)

对于多态行为,您overridePartTimeEmployee必须使用FullTimeEmployee这些方法。你在那里做的是将方法隐藏在基类中。

        public class Employee 
        {
            public Employee()
            {
                this.firstName = "Terry";
                this.lastName = "Wingfield";
            }

            public string firstName { get; set; }
            public string lastName { get; set; }

            public virtual void writeName()
            {
                Console.WriteLine(this.firstName + " " + this.lastName);
                Console.ReadLine();
            }
        }

    public class PartTimeEmployee : Employee 
    {
        public override void writeName() 
        {
            Console.WriteLine("John" + " " + "Doe");
            Console.ReadLine();
        }
    }
    public class FullTimeEmployee : Employee 
    {
        public override void writeName()
        {
            Console.WriteLine("Jane" + " " + "Doe");
            Console.ReadLine();
        }
    }

答案 3 :(得分:0)

使用C#,您可以使用“new”关键字重写基类的方法。如果省略此关键字,编译器将编译源代码,就像它存在一样。 所以我认为,问题是:新的和覆盖之间有什么区别?这是一个很大的不同。

“new”指示编译器使用您的实现而不是基类实现,但任何不直接引用您的类的代码都将使用基类实现。

“override”用于虚方法和抽象方法。这指示编译器使用方法的最后定义的实现。如果在对基类的引用上调用该方法,它将使用覆盖该对象的最后一个实现。

我希望我已经足够清楚了。