【问题标题】:Inheritance of classes that aren't related in the traditional sense of OOP继承传统意义上的 OOP 中不相关的类
【发布时间】:2014-12-07 08:02:09
【问题描述】:

我想知道我是否在 OOP 方面以正确的方式处理我的项目。我的项目由 c# 中的 Windows 控制台应用程序组成。该应用程序的重点是获取用户输入,将其转换为 sql 查询并查询连接的数据库,然后以用户请求的易于阅读的格式输出信息。我现在有以下 3 个课程:

类:commandLineInterpreter 扩展 sqlQueries

这个类打印出用户可以使用的命令。它还需要用户输入。

类:sqlQueries 扩展 dbConnect

这个类包含 sql 查询,这些查询将根据用户输入的内容查询数据库。

类:dbConnect 这个类初始化数据库连接并打印出一条消息,说明它是否成功。

如您所见,我有一个扩展 sql 查询类的 commandlineInterpreter 类,然后扩展了 db connect 类。

当我在 main() 函数中初始化命令行类时,它也会自动初始化其他扩展类。我这样做是因为如果不连接到数据库,那么命令行解释器就没有用,因为它无法提供任何答案。

我的问题是,即使这些类在 OOP 的继承意义上不相关,以这种方式进行类继承是否仍然有意义?还是有更好的方法来组织我的代码?

【问题讨论】:

    标签: c# oop inheritance extend windows-console


    【解决方案1】:

    我有点不同意这种设计,因为您的对象似乎没有关系层次结构。

    命令行解释器应该对SQL Queries 类一无所知。这是一种关注点分离,唯一的工作就是读取用户输入,然后您可以将收集到的输入简单地传递给下一个服务层,即 SQL 查询类。

    【讨论】:

      【解决方案2】:

      继承是一种非常强大的工具,与其他语言(如 C)相比,它在 OOP 语言中可用。但是,请仔细考虑何时何地应用继承,因为基本上,只有在您的设计真正实现时才必须使用它需要它。也就是说,当您确实确定存在 'B is-an A' 类型的关系时。如果您能侥幸成功,请始终选择 composition 而不是 inheritance,因为它为您的设计留下了更多的灵活性。

      例如,如果您想为DbConnect 添加一些额外的功能怎么办?您现在必须考虑此更改如何不会破坏您设计中任何子类所做的任何假设。有了组合,类就被留下来,设计得更加孤立。此外,继承还隐含地将不同类的生命周期和状态联系在一起,这意味着它们必须对齐才能使继承工作。

      您的CommandLineInterpreter 类需要以某种方式连接到数据库这一事实并不意味着必须从该类继承。只需使用组合并在需要时在解释器中创建连接。

      【讨论】:

        【解决方案3】:

        继承通常表达一种“A 是 B”的关系。例:苹果是一种水果。但是在这里你有完全不相关的类。保持它们不同,并为不同的任务创建单独的对象。

        dbConnect 类混合了两个截然不同的方面:连接到数据库和显示消息。 commandLineInterpreter 类应该是唯一与用户交互并显示消息的类。 dbConnect 类似乎是多余的。连接功能应该转到sqlQueries 类。可能在那里创建一个方法bool Connect(),您可以从命令行解释器调用该方法。布尔结果可用于显示适当的消息。

        class SqlQueries
        {
            private SqlConnection connection;
        
            public bool Connect()
            {
                Try {
                    connection = ...
                    connection.Open();
                    return true;
                } catch {
                    return false;
                }
            }
        
            ....
        }
        
        class CommandLineInterpreter 
        {
            public void Run()
            {
                var sqlQueries = new SqlQueries();
                if (sqlQueries.Connect()) {
                    Console.WriteLine("connected");
        
                    // run your interpreter here
                    ...
                } else {
                    Console.WriteLine("Connection error! Not connected.");
                }
            }
        }
        

        在 C# 类型(如类)中,属性、方法和事件具有 PascalCase。字段、方法参数和局部变量都有驼峰式。

        【讨论】:

          【解决方案4】:

          你的 commandLineInterpreter、sqlQueries、dbConnect 类之间不需要继承,因为当某些类(包括它自己的特性)还包含其他一些类的特性时需要继承。

          但是这里有一个关联(当一个类关联(当类做一些工作而下一个类做剩余时)到另一个类时的一个 OOP 概念)可以在 sqlQueries 和 dbConnect 类之间使用。

          对于关联类型的关系,使用 sqlQueries 中的 dbConnect 对象。

          【讨论】:

          • 关联类型的关系是什么样的?
          • 视情况而定。如果一个类 A 真的“拥有”一个类型 B 的实例并管理它的生命周期,那么 A 通常会在其构造函数中创建一个 B 的实例并将其分配给私有只读属性。但是,对于如何对类之间的“设计时间关系”进行编程,并没有具体的规则。这一切都非常依赖于要求,例如实例生命周期、实例的性能/处置、实例的所有权、不同时间点的信息可用性等
          猜你喜欢
          • 2014-09-02
          • 1970-01-01
          • 2013-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多