Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 抽象基类或辅助类_C#_Inheritance_Composition - Fatal编程技术网

C# 抽象基类或辅助类

C# 抽象基类或辅助类,c#,inheritance,composition,C#,Inheritance,Composition,我今天刚刚学到了一点关于写作而不是继承的知识。我想知道我是否应该把这个概念应用到我最近写的东西上 我们以前有两个几乎相同的课程,除了一些小的差异。它们包含一些基本的数据库访问功能,但操作的对象类型不同(但相关)。所以我们以前有这样的类: class BallMillDBHandler{ public BallMillDBHandler(){ ... } public void InsertTool(BallMill tool) { ... } public BallM

我今天刚刚学到了一点关于写作而不是继承的知识。我想知道我是否应该把这个概念应用到我最近写的东西上

我们以前有两个几乎相同的课程,除了一些小的差异。它们包含一些基本的数据库访问功能,但操作的对象类型不同(但相关)。所以我们以前有这样的类:

class BallMillDBHandler{

    public BallMillDBHandler(){ ... }

    public void InsertTool(BallMill tool) { ... }
    public BallMill QueryTool(string toolID) { ... }
    public void UpdateTool(BallMill tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

class DiamondToolDBHandler{

    public DiamondToolDBHandler(){ ... }

    public void InsertTool(DiamondTool tool) { ... }
    public DiamondTool QueryTool(string toolID) { ... }
    public void UpdateTool(DiamondTool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}
我采用了大多数几乎重复的方法,并将它们重构成一个
BaseToolDBHandler()
类,并从另外两个类继承了它,提供了一些抽象方法和属性来处理访问数据库参数本身的差异


BaseToolDBHandler
改为包含在数据库访问器中的帮助器类,并为它们提供一个公共接口(以前抽象的属性/方法),这有意义吗?或者我应该把它作为继承的例子吗?

继承确实倾向于被过度使用,但这似乎是一个合适的例子。在许多情况下,人们只是看到重复的代码并认为“我将使用继承通过基类删除重复的代码”。实际上,大多数重复的代码可以完全重构到另一个在多个地方使用的类中。通常使用它的类并不“相关”,它们正在做两件完全不同的事情,只是碰巧需要做一些(或一系列)小任务


当您可以说类“是”基类的实例,而不仅仅是需要访问其他地方定义的一组方法的类时,应该使用继承。在您的特定情况下,很明显这两个类都是DB处理程序。关键是,它们都服务于相同的总体目标,但它们是该目标的两种不同的可能实现。我在这里看到的唯一问题(假设您没有显示任何方法的内容)是,您可能能够将两个类合并到一个类中,但我们需要了解更多细节,以了解这是否可能或更可取

这看起来像是一个通过基类/接口对泛型和继承都有利的场景

class DBHandler<TTool> where TTool : ToolBase // or ITool
{
    public DBHandler(){ ... }

    public void InsertTool(TTool tool) { ... }
    public TTool QueryTool(string toolID) { ... }
    public void UpdateTool(TTool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}
类DBHandler,其中TTool:ToolBase//或ITool
{
公共DBHandler(){…}
公共void插入工具(TTool工具){…}
公共TTool查询工具(字符串工具ID){…}
公共无效更新工具(TTool工具){…}
公共void DeleteTool(字符串工具ID){…}
}
如果需要,可以创建一个基类(可选的抽象类)或一个接口来用作类型约束,该类型约束将保证方法体中需要工具的某些成员

示例:

var handler = new DBHandler<BallMill>();
BallMill value = handler.QueryTool("xyz");
value.SomeProperty = "New Value";
handler.UpdateTool(value);
var handler=new DBHandler();
球磨机值=handler.QueryTool(“xyz”);
value.SomeProperty=“新值”;
handler.UpdateTool(值);

我想说这绝对是继承的任务……但让我们先弄清楚一件事。组合是一种设计模式,可以而且应该在类的多重继承不是给定语言的特征的情况下使用(例如C#)

组合意味着复合类实例化类,而这些类通常是继承的。在本例中,您通过接口向实现提供契约

<> P>给你一个关于继承如何应用于代码的粗略示例,请考虑:(这不是使用构图)


使用泛型而不是继承。您希望在不同类型的对象上执行相同的操作,这正是泛型最擅长的地方。

对我来说,这似乎是继承的最佳场所,所以我就不这么说了。Neil Kennendy是对的。但是,如果您的基类只提供抽象方法和属性,并且从未提供过任何实现的功能,那么请使用接口(例如,
IDBHandler
)。这看起来确实是一个选项,但这取决于这些方法内部的情况;它们可能足够相似,也可能不够相似,因此可以起作用。我认为,让基础成为通用基础将有很大帮助。我仍然需要维护一组不同的参数来访问数据库,我认为将这些参数保存在单独的类中比在每个实例中传递它们要好。但是这是有帮助的,我想我会把它标记为被接受的答案。
QueryTool
不在接口上,我认为这个答案在我看来是不可行的。接口没有实际用途。我喜欢你关于何时使用继承的定义——它不仅仅是“陈词滥调”是一个“vs”有一个“定义,但您实际上解释了这些类服务于相同的总体目标(因此可能需要以多态方式引用它们,因此有充分的理由使用继承)。除此之外,继承并没有真正的好处,因为代码重用可以通过组合实现,而不存在继承可能带来的耦合和危险。
public interface IHandler
{
    void InsertTool(ITool tool);
    void UpdateTool(ITool tool);
    void DeleteTool(string toolID);
    //void DeleteTool(ITool tool) - seems more consistent if possible!?

    ITool QueryTool(string toolID);
}

public interface ITool
{

}

class BallMill : ITool
{
}

class DiamondTool : ITool
{
}

class BallMillDBHandler : IHandler
{

    public BallMillDBHandler(){ ... }

    public void InsertTool(ITool tool) { ... }
    public BallMill QueryTool(string toolID) { ... }
    public void UpdateTool(ITool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

class DiamondToolDBHandler : IHandler
{

    public DiamondToolDBHandler(){ ... }

    public void InsertTool(ITool tool) { ... }
    public DiamondTool QueryTool(string toolID) { ... }
    public void UpdateTool(ITool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}