我自己从一本书中学习C#并且不明白我在这里做错了什么。我有一个基类抽象类Employee
,类Director
继承自,类Partner
继承自该类。我想根据带有职位的枚举类型在Partner
类中设置职称。假设以下(MWE)代码:
public abstract class Employee
{
protected string title = "Employee"; // underlying field
public string Title { get { return title; } } // read-only property
public Employee() { // do some stuff all children need } // constructor
public virtual void Display()
{
Console.WriteLine("Title: {0}", Title);
}
}
public class Director : Employee
{
protected new string title = "Director"; // shadowing field works here
public int NumberOfProjectsManaged { get; set; } // additional property
public Director() : base() { NumberOfProjectsManaged = 0; } // constructor
public override void Display()
{
base.Display();
Console.WriteLine("Number of Projects Managed: {0}", NumberOfProjectsManaged);
}
}
public class Partner : Director
{
// there are more than two in the actual code, but this is a MWE
public enum SpecificTitle
{
Principal,
Partner
};
public Partner() : base()
{
this._setTitle(SpecificTitle.Partner); // defaults to Partner
}
public Partner(SpecificTitle jobTitle)
{
this._setTitle(jobTitle); // overloaded ctor allows user to specify
}
private void _setTitle(SpecificTitle jobTitle)
{
switch (jobTitle)
{
case SpecificTitle.Principal:
this.title = "Principal";
break;
case SpecificTitle.Partner:
default:
this.title = "Partner";
break;
}
}
}
Director
班级工作正常,标题总是"导演"如预期的。但是,Partner
类的标题始终为"员工"而不是"合作伙伴"或"校长"。如果我只使用默认构造函数,那无关紧要:
Partner DefaultTitle = new Partner(); // title = "Employee"
或者如果我指定一个:
Partner PrincipalTitle = new Partner(Partner.SpecificTitle.Principal);
要输出值,我使用继承的Display()
方法:
DefaultTitle.Display();
请帮助我理解我做错了什么。
答案 0 :(得分:3)
基础Employee.Display()
方法打印其title
字段的值。 Director
类定义new title
字段,该字段隐藏(不覆盖)基本Employee.title
字段。 Partner
和Director
类适用于Director.title
,与基本Employee.title
字段无关。重构您的Director
课程,以移除new title
字段。
答案 1 :(得分:2)
问题是你使用这一行:
protected new string title = "Director";
new
关键字隐藏了Employee
的{{1}}定义。
如果那是你想要的,那不是真正的问题。当您将title
执行路径调用回该方法的Partner.Display
定义时,会出现问题。在Employee
定义中,它使用隐藏的Employee
字段。
当您在title
课程中设置title
时,您只在Partner
课程中设置new
title
字段,而不是基类Director
' Employee
字段。
要解决此问题,请删除上述中提到的行。然后,您将希望使title
构造函数看起来像这样。
Director
答案 2 :(得分:1)
看起来问题出现在Director类中,特别是以下行:
protected new string title = "Director"; // shadowing field works here
你真的不需要它,你也可能也想改变你的构造函数。继承人主任
public class Director : Employee
{
//protected string title = "Director"; // shadowing field works here
public int NumberOfProjectsManaged { get; set; } // additional property
public Director() : base() {
NumberOfProjectsManaged = 0;
title = "Director";
} // constructor
public override void Display()
{
base.Display();
Console.WriteLine("Number of Projects Managed: {0}", NumberOfProjectsManaged);
}
}
对于测试,我使用了这个:
Partner DefaultTitle = new Partner();
DefaultTitle.Display();
Partner PrincipalTitle = new Partner(Partner.SpecificTitle.Principal);
PrincipalTitle.Display();
Director director = new Director();
director.Display();
并获得以下输出:
Title: Partner
Number of Projects Managed: 0
Title: Principal
Number of Projects Managed: 0
Title: Director
Number of Projects Managed: 0
答案 3 :(得分:1)
为了满足您在Director类
中所有构造函数中定义标题的需要public Director() : base() {
// other stuffs
this.title = "Director";
}
// other constuctors
public Director(object someparam) : this() {
// do some stuff
}
因此,每次调用构造函数时,它都会冒泡到基础构造函数。
答案 4 :(得分:0)
您可以设置enum' SpecificTitle'来自合作伙伴课程的ouside。
public enum SpecificTitle
{
Principal,
Partner
};
并在Employee和Director类中使用标题类型作为' SpecificTitle'枚举
public abstract class Employee
{
protected SpecificTitle title = "Employee";
//others
}
public class Director : Employee
{
protected SpecificTitle title = "Director";
//others
}
并将开关盒更换为:
switch (jobTitle)
{
case SpecificTitle.Principal:
this.title = SpecificTitle.Principal;
break;
case SpecificTitle.Partner:
default:
this.title = SpecificTitle.Partner;
break;
}
或确定你应该用这一行替换开关盒
private void _setTitle(SpecificTitle jobTitle)
{
this.title = jobTitle;
}
我没有测试过这个,但是这个逻辑可以和你一起使用。
答案 5 :(得分:0)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Partner DefaultTitle = new Partner(); // title = "Employee"
DefaultTitle.Display();
Console.ReadLine();
}
}
public abstract class Employee
{
public virtual string title { get; set; } // underlying field
public string Title
{
get { return title; }
} // read-only property
public Employee() { // do some stuff all children need
this.title = "Employee";
} // constructor
public virtual void Display()
{
Console.WriteLine("Title: {0}", Title);
}
}
public class Director : Employee
{
public override string title { get; set; } // shadowing field works here
public int NumberOfProjectsManaged { get; set; } // additional property
public Director() : base() {
this.title = "Director";
} // constructor
public override void Display()
{
base.Display();
}
}
public class Partner : Director
{
// there are more than two in the actual code, but this is a MWE
public override string title { get; set; }
public enum SpecificTitle
{
Principal,
Partner
};
public Partner() : base()
{
this._setTitle(SpecificTitle.Partner); // defaults to Partner
}
public Partner(SpecificTitle jobTitle)
{
this._setTitle(jobTitle); // overloaded ctor allows user to specify
}
private void _setTitle(SpecificTitle jobTitle)
{
switch (jobTitle)
{
case SpecificTitle.Principal:
this.title = "Principal";
break;
case SpecificTitle.Partner:
default:
this.title = "Partner";
break;
}
}
}
}
终于搞定了!对不起我的最后一个答案。我将基类设置为虚拟,因此任何子类都可以覆盖它的值。
robwaminal是正确的,在Partner
类中设置标题只设置它的直接父级的标题Director
。