假设我有三个或更多课程:工程师:员工:人员。请考虑以下示例(假装我现在使用StringBuilder和其他更好的实践)
public abstract class Person
{
public string Name{get;set;}
public string SaySomething()
{
string introduction = "Hello, my name is " + Name + ". ";
return OnSaySomething(introduction);
}
protected virtual string OnSaySomething(string thoughts)
{ return thoughts; }
}
public abstract class Employee : Person
{
public string Employer{get;set;}
protected override string OnSaySomething(string thoughts)
{
return thoughts + "I work for " + Employer + ".";
}
}
public class Engineer : Employee
{
public string Discipline{get;set;}
protected override string OnSaySomething(string thoughts)
{
return thoughts + "My discipline is " + Discipline + ".";
}
}
使用上面的例子,输出:
Engineer engineer = new Engineer();
engineer.Name = "Dennis Ritchie";
engineer.Discipline = "Software Engineering";
Console.WriteLine(engineer.SaySomething());
会产生
您好,我的名字是Dennis Ritchie。我的学科是软件工程。
是否可以构建这些类,以便每个覆盖"粘贴"更多功能,输出为:
您好,我的名字是Dennis Ritchie。我为...工作。我的学科是 软件工程。
有没有一种标准的方法来实现这种想法?我的下意识解决方案是在OnSaySomething()
密封Employee
并引入一种新方法OnEmployeeSaySomething()
Engineer
将覆盖它自己的特定逻辑。
由于SaySomething()
,OnSaySomething()
和OnEmployeeSaySomething()
都在Engineer
公开,所以这似乎很快就会变得混乱(如果层次结构中有另一个级别,那就更糟了) !)。我想知道是否有更好的解决方案。谢谢你的关注!
TL; DR :我希望在不破坏基本逻辑的情况下进行扩展。但我不希望我的课程变得非常混乱。
修改
有人指出一个好的(也许是显而易见的)解决方案,这是我提供一个坏榜样的错。相反,我们要在这种情况下验证一些数据:
public class Level0
{
public string Data{get;set;}
public bool IsValid()
{
if (Data == null) return false;
else return OnIsValid();
}
protected virtual bool OnIsValid()
{return true;}
}
public class Level1 : Level0
{
public string Data_Level1{get;set;}
protected override OnIsValid()
{
if (Data_level1 == null) return false;
else return OnLevel1IsValid();
}
protected virtual bool OnLevel1IsValid()
{return true;}
}
public class Level2 : Level1
{
public string Data_Level2{get;set;}
protected override OnLevel1IsValid()
{
return Data_level2 != null;
}
}
答案 0 :(得分:1)
利用基数:
protected override string OnSaySomething(string thoughts)
{
return base.OnSaySomething() + thoughts + "My discipline is " + Discipline + ".";
}
答案 1 :(得分:1)
您需要调用函数的基本版本,以便下一个更高级别的代码可以构建其字符串并将其返回到派生版本,以便它可以添加其他文本。
public abstract class Employee : Person
{
public string Employer{get;set;}
protected override string OnSaySomething(string thoughts)
{
return base.OnSaySomething(thoughts)+ "I work for " + Employer + ".";
}
}
public class Engineer : Employee
{
public string Discipline{get;set;}
protected override string OnSaySomething(string thoughts)
{
return base.OnSaySomething(thoughts) + "My discipline is " + Discipline + ".";
}
}
编辑: 使用更新的代码,它仍然是一样的
public class Level1 : Level0
{
public string Data_Level1{get;set;}
protected override bool OnIsValid()
{
return base.OnIsValid() && Data_level1 != null;
}
}
public class Level2 : Level1
{
public string Data_Level2{get;set;}
protected override OnLevel1IsValid()
{
return base.OnIsValid() && Data_level2 != null;
}
}
EDIT2:为了使它“自动”你几乎已经完成了实现,你可以做的另外一件事就是标记属性sealed
,这样就可以在链的下方再次覆盖它,但是我会不建议使用这种方法,而是使用前一个示例中的覆盖。
public class Level1 : Level0
{
public string Data_Level1 { get; set; }
protected override sealed bool OnIsValid()
{
if (Data_Level1 == null) return false;
else return OnLevel1IsValid();
}
protected virtual bool OnLevel1IsValid()
{
return true;
}
}
public class Level2 : Level1
{
public string Data_Level2 { get; set; }
protected override sealed bool OnLevel1IsValid()
{
return Data_Level2 != null;
}
}
答案 2 :(得分:1)
您需要调用基本版本。
DateTime
答案 3 :(得分:0)
我不太明白你的意思是“我想扩展,而不是覆盖”因为你显然使用了“override”关键字。无论如何,我可以提出以下解决方案:
public abstract class Person
{
public string Name{get;set;}
public virtual string SaySomething()
{
return = "Hello, my name is " + Name + ". ";
}
}
public abstract class Employee : Person
{
public string Employer{get;set;}
public override string SaySomething()
{
return base.SaySomething() + "I work for " + Employer + ". ";
}
}
public class Engineer : Employee
{
public string Discipline{get;set;}
public override string SaySomething()
{
return base.SaySomething() + "My discipline is " + Discipline + ". ";
}
}