C# 多态性意外结果
为了更好地理解多态性,我构建了一个小测试,它返回了意想不到的结果 所以我们的想法是用virtual/override关键字覆盖基类方法,但我似乎不需要这些C# 多态性意外结果,c#,class,polymorphism,C#,Class,Polymorphism,为了更好地理解多态性,我构建了一个小测试,它返回了意想不到的结果 所以我们的想法是用virtual/override关键字覆盖基类方法,但我似乎不需要这些 public class Employee { public Employee() { this.firstName = "Terry"; this.lastName = "Wingfield";
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();
}
}
使用上面的代码,我希望得到如下结果:
特里·维恩菲尔德
特里·温菲尔德
特里·温菲尔德
但是,以下内容被写入控制台:
特里·温菲尔德
无名氏
无名氏
我认为后者不起作用,因为它需要ovrride关键字
所以问题是为什么我看到后面的名字没有合适的关键字
我希望这是足够清楚的阅读
关于,这称为方法隐藏。您只是将基类方法隐藏在派生类中。你应该得到警告,但这是完全合法的。有关更多信息,请参阅。您可能还想看看问题这称为方法隐藏。您只是将基类方法隐藏在派生类中。你应该得到警告,但这是完全合法的。有关更多信息,请参阅。您可能还想看看问题您显示的代码中没有多态性 将其更改为:
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。显示的代码中没有多态性 将其更改为:
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。对于多态行为,必须在PartTimeEmployee和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();
}
}
对于多态行为,必须重写PartTimeEmployee和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();
}
}
使用C,您可以使用new关键字重写基类的方法。如果省略此关键字,编译器将编译源代码,就像它存在一样。 所以我想问题是:新的和覆盖的区别是什么?这是一个很大的区别 new指示编译器使用您的实现而不是基类实现,但是任何不直接引用您的类的代码都将使用基类实现 重写用于虚方法和抽象方法。这指示编译器使用最后定义的方法实现。如果在对基类的引用上调用该方法,它将使用在该对象上重写它的最后一个实现
我希望我已经说得够清楚了。使用C,您可以使用new关键字重写基类的方法。如果省略此关键字,编译器将编译源代码,就像它存在一样。 所以我想问题是:新的和覆盖的区别是什么?这是一个很大的区别 new指示编译器使用您的实现而不是基类实现,但是任何不直接引用您的类的代码都将使用基类实现 重写用于虚方法和抽象方法。这指示编译器使用最后定义的方法实现。如果在对基类的引用上调用该方法,它将使用在该对象上重写它的最后一个实现 我希望我已经说得够清楚了。这是因为
子类中的writeName将版本隐藏在基类中,您应该看到编译器警告。如果您将这三个版本全部转换为Employee,您应该会看到第一个结果。@jlRise非常感谢您。这是因为子类中的writeName将版本隐藏在基类中,您应该看到编译器警告。如果你把这三个问题都交给员工,你应该会看到第一个结果。@jlris非常感谢你。这并不能回答他的问题。他问了关于方法实现的多态性,以及为什么在他不使用覆盖的情况下调用基类方法的实现。@Alan方法隐藏确实解释了他看到的行为。他的问题是,为什么他不使用覆盖就不能得到基类方法的实现。正确的答案是,因为他没有使用对基类类型的引用。他正试图测试使用虚拟方法与不使用虚拟方法之间的区别。通过使用基类型的变量,他无法证明他的错误,无论它是否是方法隐藏。@Selman22谢谢你们的评论,但这并没有回答我的问题。这当然是问题的一部分,但不是全部。尽管如此,我还是很感谢你给我的所有时间来帮助我解决这个问题。这并不能回答他的问题。他问了关于方法实现的多态性,以及为什么在他不使用覆盖的情况下调用基类方法的实现。@Alan方法隐藏确实解释了他看到的行为。他的问题是,为什么他不使用覆盖就不能得到基类方法的实现。正确的答案是,因为他没有使用对基类类型的引用。他正试图测试使用虚拟方法与不使用虚拟方法之间的区别。通过使用基类型的变量,他无法证明他的错误,无论它是否是方法隐藏。@Selman22谢谢你们的评论,但这并没有回答我的问题。这当然是问题的一部分,但不是全部。尽管如此,我还是感谢您为帮助我解决这个问题所花费的所有时间。我看到您在实例化子类时添加了Virtual/Override关键字,但没有提到引用基类。感谢您的时间。我看到您在实例化子类时添加了Virtual/Override关键字,但没有提到引用基类。谢谢您的时间。很好的信息性评论,但可能与主题有关。我知道发生了什么,应该输出什么,但是代码中有一个错误。仍然是一个伟大的评论!将有助于未来的读者。谢谢。很好的信息性评论,但可能与主题有关。我知道发生了什么,应该输出什么,但是代码中有一个错误。仍然是一个伟大的评论!将有助于未来的读者。谢谢。考虑到您提供的代码和答案,我会将此标记为已回答。如果我可以问的话,是为了帮助未来的读者。为什么需要引用基类来实例化多态行为的子类?谢谢,谢谢。这是一个很好的信息更新,可以与您的答案一起使用。考虑到您在答案中提供了代码,我会将此标记为已回答。如果我可以问的话,是为了帮助未来的读者。为什么需要引用基类来实例化多态行为的子类?谢谢,谢谢。一个伟大的信息更新,以配合您的答案。