My situation is something like this:
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"""
There is also a condition that if property_b is less than property_a, then property_a is invalid and thus the result of some_value is also invalid.
What I mean is this... if at any time during the object's lifetime, calling property_b would yield a number lower than calling property_a, there's a problem. However, property_b is not a field. It is determined dynamically based on n fields, where n >= 1. It is impossible to check this condition while setting property_b because property_b itself is never set. Really, setters are not anticipated to be used anywhere here. All fields are likely to be set in the constructors and then left alone. This means that property_a will be known in the constructor for AbstractClass and property_b only after evaluating the constructor for the concrete classes.
<update>
The fundamental problem is this: I need to check property_a for validity, but when property_a is set (the most intuitive place to check it), property_b is undefined.
</update>
I want to ensure that property_b is never less than property_a. How should I handle it?
Check property_a against property_b in...
AbstractClass.__init__. This is actually impossible becauseproperty_bhasn't been defined yet.AbstractClass.property_a. This seems problematic because I would be throwing an exception in a getter.- Each concrete implementation of
property_b. Not only would I be throwing an exception in a getter, I would be duplicating code. Alsoproperty_bdoes not logically depend onproperty_a. AbstractClass.some_value. This is still throwing an exception in a getter. Also, it is logically impossible forproperty_bto be less thanproperty_aall the time, not just when trying to determinesome_value. Further, if subclasses decide to add other properties that depend onproperty_a, they may forget to check it againstproperty_b.- Concrete setters for
property_b. These don't exist.property_bis sometimes determined from a value set in the constructor, sometimes calculated from multiple values. Also, code duplication. - Concrete class
__init__methods. Code duplication. Someone may forget. - ???
UPDATE
I think what is causing confusion is that property_b is not simply a field. property_b relies on calculations. It is really more a function than a property, if it helps to think about it that way.