我对抽象关系“IS-A”和界面“HAS-A”功能有一个疑问。
例如,我有以下课程:
public interface IReport
{
int code { get; set; }
String description { get; set; }
void SetReport(String description, int code);
void DeleteReport();
}
public abstract class BugReport : IReport
{
public int? code { get; set; }
public String description { get; set; }
public void IReport.SetReport(String description, int code)
{
this.description = description;
this.code = code;
}
public void IReport.DeleteReport()
{
this.description = "";
this.code = null;
}
}
我知道我的BugReport类将始终具有相同的实现,但如果需要,我可以在子类上扩展它。此标准将匹配抽象类“用法”,但不匹配“IS-A”关系(例如,如果在此类上使用):
public abstract Parser : BugReport
{
}
我的Parser是BugReport吗?显然不是,但它似乎是最合乎逻辑的选择,如果我将我的BugReport作为一个接口,我将不得不实现我继承的所有类的功能。所以我做错了,我应该继续使用独立于IS-A关系不匹配的抽象,还是应该切换到接口?
答案 0 :(得分:1)
首先,这对我来说似乎是多余的;
int code { get; set; }
String description { get; set; }
void SetReport(String description, int code);
拥有属性设置器和专门设置它们的方法完全是多余的。如果添加属性会发生什么?你改变了SetReport
吗?使用这种方法会导致一连串的变化吗?你是否添加了一个带有第三个参数的重载来满足新属性并进一步使类复杂化?
保持界面简洁;提供一种做某事的方法,否则你只会混淆班上的消费者。
除此之外,如果你不知道Parser
是什么,那么没有人能说它是否是一个BugReport。但纯粹基于词典,我会说不。在我所知道的没有字典中,BugReport = Parser。
答案 1 :(得分:0)
你应该考虑构成而不是继承。创建一个BugReport
类,并在Parser
类中使用它的实例来获得所需的功能,而不是通过继承来获取功能。
您可以在子类上扩展BugReport
类的功能,并根据需要将它们注入Parser
类。
答案 2 :(得分:0)
根据你的问题,我也认为你误解了IS-A和HAS-A。
您还没有举例说明HAS-A关系。上面编写代码的方式,BugReport是IReport,Parser是BugReport(因此也是IReport)。
在这种情况下执行has-a关系的方法是Parser是否具有属于IReport的属性。例如:
public class Parser
{
public Parser(IReport reporter)
{
this.Report = reporter;
}
public IReport Report { get; set; }
}