3

我有一些 c# 代码已经运行了一段时间了.. 我不得不说,虽然我了解 OO 原则的基础知识,但显然有不止一种方法可以给猫剥皮(尽管我讨厌这个词!) .

因此,我有一个基本抽象类,它充当基本数据服务类,如下所示(为了便于阅读而进行了很多简化):

public abstract class dataservice
{
    public enum OutputType : int { XmlTOJson = 0, Xml = 1, Json=2 }

    protected object SomeDBcall(string StoredProcedure)
    {
        // Just assume we are using SQLclient/DB access..
        object SomeReturnObjValue = db.ExecuteScalar(cmd);
        return SomeReturnObjValue;
    {
}

..所以基本上我可能在抽象类中有一些基本的数据库检索/更新/删除调用..主要是因为我的应用程序中有任何数据库操作的基础。

所以现在我们有一个实现基类的类,在我的例子中是一个客户类:

public class Customer : dataservice
{
    Public String CustomerDoSomething(string SomeDataEtc)
    {
        // Ok, so again for simplicity sake, we are going to use the base class to 
        // call a DB retrieve 
        object ReturningObj = SomeDBcall("my stored procedure");
        return ReturningObj.ToString();
    }
}

所以我想我的问题是:上述方法“可以”使用吗?考虑到如果需要可以覆盖虚拟方法,但是在这种情况下,我只希望基类使用那些受保护的方法作为调用 DB 操作的方法。

非常感谢任何清晰/指导!

4

5 回答 5

1

当然,这“没问题”,尽管我认为基类没有理由成为abstract. abstract类非常适合实现一些常见的逻辑,而其余的则由派生类来实现。但是,您没有抽象/虚拟方法,所以我在这里看不到重点。

于 2012-06-07T16:03:21.203 回答
1

也许您可以让您的抽象类具体化,并将其用作某种帮助类来处理您需要的数据库相关内容。就示例代码而言,不需要有多个数据库访问类,只需不同的参数即可。

于 2012-06-07T17:55:12.420 回答
1

您可能希望查看模板模式来定义基类(抽象或非抽象)中的接口,其中定义了可以在具体子类中覆盖的受保护虚拟钩子。正如另一张海报所提到的,如果您只是打算将数据库服务添加到您的每个领域,您可能希望将基本的数据库服务方法封装到帮助程序类中,而不是从数据库服务派生。

感谢@jgauffin 质疑我的 LSP 违规声明。它不正确,已被删除。在很多情况下,需要通过子类扩展基类的公共接口。当然,这样做需要小心,在执行特定于 Y 的操作 A() 时,您有一个 Y 的实例,而不是 X 或 Z,假设 Y 和 Z 都派生自 X,其中 Y 添加了新的公共方法 A() 和 Z 没有。

OP 上下文中的模板模式示例将允许在子类中更好地封装自定义功能,而无需扩展公共接口。但是,这仅在没有对子类实例施加外部影响的情况下才有效,例如 OP 的 SomeDataEtc 参数。当实例是不可变的时,这最有效。

public abstract class DataService
{
    protected object myWidget = new Widget();
    public object SomeDataBaseCall(string storedProcedure)
    {

        DoSomeCustomThing();

        //do db stuff
        object SomeReturnObjValue = db.ExecuteScalar(storedProcedure);
        return SomeReturnObjValue;
    }

    protected void DoSomeCustomThing() {}
}


public class Customer : DataService
{
    override protected void DoSomeCustomThing()
    {
        // do your custom thing here
    }
}

此外,在 OP 的示例中,在派生类的新公共方法中使用委托来调用基类的 SomeDBCall 方法来执行存储过程似乎是明智的。如果您对数据库访问方法进行冗余编码,那么建议的继承没有任何好处。

正如在其他地方也提到的那样,使用组合而不是数据服务功能的继承可能会更好。

于 2012-06-07T18:17:55.000 回答
1

概述

很多时候,你的“发展本身会指导你”。

实用的答案。

(1) 您定义了一个基类“dataservice”,并且从该类中,将基于其他几个类。您标记为“抽象”,这很好。这并不意味着自己有变量。

一些开发人员不会将该类标记为“抽象”,这不是强制性的,但是,它不是一个坏主意,但是,它是一个“好的实践”,标记为“抽象”。

并且,将添加其他方法,由子类使用,可能会被覆盖,也可能不会。

要知道,这些方法是受保护的,并不意味着在对象之外使用,而是由其他方法使用。没关系。

也许,稍后,可能需要在类外使用方法,并且可能必须更改为 public。

(2) 添加一个子类“Customer”,它是“DataService”的后代。添加一个必须在类外使用的方法,并标记为“public”,很好。

它仅供此类使用,而不是父类。因此,不需要“虚拟”或“覆盖”。好的。

(3) 你的例子很简单。你做的大部分事情,在我看来都很好。

最终,当您添加更多代码时,事情可能会发生变化,例如基类中私有的方法可能会变为公共方法,或者您可以“重命名”或“重构”一个方法,例如“dosomething”,并发现它更好在基类中,或者可能不是。

概括

还有其他答案,即提及、规则或概念。在我看来,它们还可以,但是,请跳过您正在学习更好地使用 OOP 的事实。有些人只是想“一口吃掉蛋糕”,这不是一个好主意。

PD“can ur skin ur rabbit”对我来说听起来更好。

干杯。

于 2012-06-07T18:36:21.277 回答
0

不。猜猜你下面的数据访问对象模式(DAO)。无论哪种方式,您Customer都不是您的数据访问类。它使用一个类进行数据访问。我的意思是你的 DAO 应该支持组合而不是继承。

就像是:

public class Customer : IDataAccessObject
{
    public Customer()
    {
        _dataAccess = new DataAccess();
    }

    public string CustomerDoSomething(string SomeDataEtc)
    {
        object ReturningObj = _dataAccess.SomeDBcall("my stored procedure");
        return ReturningObj.ToString();
    }
}

为什么?你的对象得到一个单一的职责,这意味着更容易扩展和重构它们。

您可以阅读有关SOLID的信息,这是一些基本的编程原则。

由于您是 .NET 开发人员,我还建议您接受命名准则

于 2012-06-07T18:17:14.083 回答