This will be a example-driven presentation. The first set of examples looks at
int which should be restricted to a value from one through ten.
First I'll look at the problems in the traditional approach, passing an
to a function and checking to ensure it is within range.
Next I'll encapsulate the
int in a (regular) class
OneToTen, which allows
the movement of the test into the constructor. Although this guarantees that
objects will be created correctly, such objects are mutable so they can be
modified to be invalid after creation.
The solution is to use
@dataclass together with the
frozen=True option, and
__post_init__ function to check the validity of the object once it's
been initialized. Because such an object is invariant, it cannot be later
modified into an invalid state. This ensures that the new type can only ever
exist as a legitimate value.
Next I'll use this technique to create a
Person type that is composed of
EmailAddress fields, each of which validates
itself. Finally, I'll compose