【发布时间】:2009-10-16 14:28:38
【问题描述】:
我的情况是这样的:
class AbstractClass:
def __init__(self, property_a):
self.property_a = property_a
@property
def some_value(self):
"""Code here uses property_a but not property_b to determine some_value"""
@property
def property_a(self):
return self.property_a
@property
def property_b(self):
"""Has to be implemented in subclass."""
raise NotImplementedError
class Concrete1(AbstractClass):
"""Code here including an implementation of property_b"""
class Concrete2(AbstractClass):
"""Code here including an implementation of property_b"""
还有一个条件,如果property_b小于property_a,那么property_a是无效的,那么some_value的结果也是无效的。
我的意思是……如果在对象的生命周期中的任何时候,调用property_b 会产生一个低于调用property_a 的数字,那就有问题了。但是,property_b 不是字段。它是根据 n 字段动态确定的,其中 n >= 1。在设置 property_b 时无法检查此条件,因为从未设置过 property_b 本身。实际上,预计不会在此处任何地方使用 setter。所有字段都可能在构造函数中设置,然后单独放置。这意味着 property_a 将在 AbstractClass 和 property_b 的构造函数中知道在评估具体类的构造函数之后。
根本问题是:我需要检查property_a 的有效性,但是当设置property_a 时(最直观的检查位置),property_b 未定义。
我想确保property_b 永远不会小于property_a。我该如何处理?
检查property_a 与property_b in...
-
AbstractClass.__init__。这实际上是不可能的,因为尚未定义property_b。 -
AbstractClass.property_a。这似乎有问题,因为我会在 getter 中抛出异常。 -
property_b的每个具体实现。我不仅会在 getter 中抛出异常,还会复制代码。此外property_b在逻辑上不依赖于property_a。 -
AbstractClass.some_value。这仍然在 getter 中引发异常。此外,property_b一直小于property_a在逻辑上是不可能的,不仅仅是在尝试确定some_value时。此外,如果子类决定添加依赖于property_a的其他属性,他们可能会忘记对照property_b进行检查。 -
property_b的混凝土固定器。这些是不存在的。property_b有时由构造函数中设置的值确定,有时由多个值计算得出。另外,代码重复。 - 具体类
__init__方法。代码重复。有人可能会忘记。 - ???
更新
我认为引起混淆的是property_b 不仅仅是一个字段。 property_b 依赖于计算。如果这样考虑的话,它实际上更像是一个函数而不是一个属性。
【问题讨论】:
-
请记住,我是作为自己做过这件事的人说的:您是否认为您在某处使事情过于复杂?我不太了解您的问题,但定义三个属性肯定不会this 复杂。你确定没有 90% 的解决方案可以实施吗?
-
好吧,我可以将属性 b 和一些值提取到子类中,但是我会重复代码,而我的架构的整个目标是让超类尽可能多地完成子类的工作尽可能小。我在这个模块中有 4 个级别的 12 个类,但实际代码只有 140 行。该架构几乎可以轻松解释,反映了问题域,并以“叶子”类结束,这些类非常小,即使有(大量)文档,通常也可以将它们放在一个屏幕上。
-
我认为 90% 的解决方案将采用 Alex Martelli 的建议,但为了简化事情,让子类永远不会改变任何影响属性 b 的东西。然后我可以在每个构造函数的末尾调用验证器。