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_b
hasn'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_b
does not logically depend onproperty_a
. AbstractClass.some_value
. This is still throwing an exception in a getter. Also, it is logically impossible forproperty_b
to be less thanproperty_a
all 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_b
is 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.