【问题标题】:OOP: class inheritance to add just one property vs constructor argumentOOP:类继承仅添加一个属性与构造函数参数
【发布时间】:2013-01-22 10:11:15
【问题描述】:

我是 OOP 的新手,我处于以下情况:我有一个类似报告“引擎”的东西,用于多个报告,唯一需要的是配置文件的路径。

我将用 Python 编写代码,但这是一个不可知的问题。所以,我有以下两种方法

A) class ReportEngine 是一个抽象类,除了配置文件的路径外,它具有所需的一切。这样你只需要实例化 ReportX 类

class ReportEngine(object):
    ...

class Report1(ReportEngine):
    _config_path = '...'

class Report2(ReportEngine):
    _config_path = '...'

report_1 = Report1()

B) 类 ReportEngine 可以通过配置文件路径实例化

class ReportEngine(object):
    def __init__(self, config_path):
        self._config_path = config_path
    ...

report_1 = ReportEngine(config_path="/files/...")

哪种方法是正确的?万一这很重要,报表对象将被插入到另一个类中,使用组合。

【问题讨论】:

    标签: oop inheritance language-agnostic


    【解决方案1】:

    恕我直言,如果您需要实现彼此不同的报表引擎,A) 方法会更好。如果您的报告使用不同的逻辑填充,请遵循此方法。

    但是,如果您的报告引擎之间的唯一区别是 _config_path,我认为 B) 方法适合您。显然,这样一来,无论报告类型如何,您都将拥有一个共享逻辑来构建每个报告。

    【讨论】:

      【解决方案2】:

      一般来说,将每个报告所具有的所有内容都放在超类中。将特定的东西放在子类中。

      因此,在您的情况下,将 _config_path 放在超类 ReportEngine 中,就像在 B) 中一样(因为每个报告都有一个 _config_path),但要实例化A) 中的特定报告,而每个报告都可以设置自己的路径。

      我不了解 Python,但快速搜索了 Python 3.0+ 的正确语法,我希望它有意义:

      class ReportEngine(object):
          def __init__(self, config_path):
              self._config_path = config_path
      
          def printPath(self):
              print self._config_path
          ...
      
      class Report1(ReportEngine):
          def __init__(self):
              super().__init__('/files/report1/...')
      

      然后一个

      reportObj = Report1()
      reportObj.printPath()
      

      应该打印

      '/files/report1/...'
      

      【讨论】:

      • 你的蟒蛇技能完全可以接受!但我仍然不完全认为这是正确的方法。这样做我们失去了抽象超类,同时我们得到了几个子类。我认为如果只有并且只有一种方法可以创建 Report 对象(这样您可以实例化子类或传递路径的超类),那会更好。再说一次,我对 OOP 有点陌生,还没有最好的把握。感谢您的回答!
      • 我的意图确实是ReportEngine 类是abstract,但我不知道它在Python 中的语法是怎样的。快速搜索表明这甚至是不可能的,但有一种解决方法:boduch.ca/2010/04/python-abstract-class.html 然后你走的路又取决于不同类中的功能。如果您的具体 ReportX 类在 config_path 中没有区别,则创建层次结构没有意义。如果它们在更多方面有所不同,由于关注点分离,您会对代码感到满意。
      • 在您的示例中,我可以实例化 report1 = ReportEngine(path_conf_1),并且该对象将是完整且功能齐全的。这在某种程度上意味着它不是一个抽象类,对吧?顺便说一句,Python 没有抽象声明,但这是这种语言的哲学/文化:你是成年人,你知道自己在做什么。如果最终你真的想要,没有任何保护措施会阻止你解决(私有变量会发生类似的事情)。
      • 那么我担心这个话题并不是真的与语言无关。如果您使用具有“抽象类”概念的语言,我的解决方案是合适的。恐怕我对 Python 没有更好的主意。无论如何,您都可以坚持这种 OOP 方式,并且始终正确使用它,因为您知道自己在做什么。但是,创建 Report 实例的方法不止一种。我认为您将不得不选择较小的邪恶:)
      • 呵呵,虽然你说的很对,但我认为这不是重点。抽象类的定义不就是因为缺少方法和属性而无法实例化的类吗?即:不完整。在您的代码中,ReportEngine 是一个完整的类,并且创建另一个扩展类,使用父级的构造函数与仅实例化传递参数的超类完全相同。我会说你有两种方法中“最糟糕的”,A 和 B :)。
      【解决方案3】:

      基本上,主要区别在于方法 A 比 B 更灵活(一份报告中不相互更改不会影响其他报告),而 B 更简单、更清晰(准确显示差异在哪里)但更改会影响一份报告类型需要更多的工作。如果您很确定报告不会及时更改 - 选择 B,如果您认为未来不会出现差异 - 选择 A。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-20
        • 1970-01-01
        • 2021-05-30
        • 1970-01-01
        • 2011-12-26
        • 1970-01-01
        相关资源
        最近更新 更多