Home | Trees | Index | Help |
|
---|
Package harold :: Package prog :: Package abstract |
|
It is common in object oriented languages to define a class which provides common methods to several subclasses, but is not supposed to be instanciated, generally because it is missing some methods. Such a class is known as an abstract class.
Being weakly typed, Python does not provide any explicit construct for abstract classes. Indeed, so called abstract classes can be instanciated and this will not even be a problem as long as missing methods are not invoked. The drawback of this flexibility is that when such missing method is invoked, an exception is raised at a point of the program where it can be quite difficult to find the faulty instanciation.
This package provides an infrastructure allowing to explicitely define abstract (i.e. missing) members, which has three advantages, without losing Python flexibility:AttributeError
raise by actually
missing members,
The package implements the notion of abstract member, i.e. a method or property which is not implemented by the class and has to be implemented by a subclass.
abstract.attr_r
and abstract.attr_rw
can
be used in class declaration to provide the semantics of an abstract
readable (resp. readable and writable) attribute. They can be used as
decorators of a dummy method named after the attribute, whose docstring
will be used as the docstring of the attribute (it may seem strange at
first sight to declare attributes as methods, but it gives an
homogeneous and nice look to abstract classes, and makes the setting of
a docstring more convenient).
abstract.method
can be used as a function decorator to
provide the semantics of an abstract method.
Any attemps to access an abstract attribute will raise
AbstractAttributeException
. Any attempt to invoke an
abstract method will raise an
AbstractMethodInvocationException
.
harold.prog.abstract.member
class AbstractClass (object): __metaclass__ = AbstractableClass @abstract.method def m (self, x): pass class ConcreteClass (object): def m (self, x): return x class CorrectInheritance (ConcreteClass, AbstractClass): pass class MisleadingInheritance (AbstractClass, ConcreteClass): pass
The class CorrectInheritance
is concrete, since the
MRO resolves method m
as its concrete definition in
ConcreteClass
. On the other hand,
MisleadingInheritance
is abstract because according to
the MRO, AbstractMethod.m
overrides
ConcreteMethod.m
.
AbstractableClass
(see below), failing to do
so will issue an
{AbstractOverridesConcreteWarning<harold.prog.abstract.exceptions.AbstractOverridesConcreteWarning>}.
This package also provides the AbstractableClass
metaclass. Any class of
this metaclass has a readonly attribute abstract
,
indicating if it contains or inherits non-overridden abstract members
or cycles. In this case, it will also have read-only attributes
abstract_members
and abstract_cycles
.
AbstractableClass
will issue an AbstractClassInstantiationWarning
, unless
it has a default implementation (see.below).
class Circle: def radius (self): return self.diameter()/2 def diameter (self): return self.perimeter()/math.pi def perimeter (self): return self.radius()*math.pi*2
That class has no abstract method, since all are implemented. However, it is abstract, since none of its method will work properly (they will all result in a stack overflow) unless at least one of them is overridden. Those three methods are all implemented, but they form an abstract cycle (or dependancy cycle) which must be broken by changing one of the implementations.
Each abstract cycle is declared as a tuple of methods which form the cycle. All abstract cycles are declared as a list in a class attribute named__abstract_cycles__
. Abstract cycles
will not prevent the methods to be called, but an
AbstractableClass
containing abstract cycles will
recognizes itself as abstract, just as if it contained an abstract
member.
Abstractable classes have an attribute
default_implementation
. If the class is concrete (i.e.
if its attribute abstract
is false), the attribute is
read-only and equals the class. It the class is abstract, the
attribute is read-write. Any concrete subclass of the abstract class
can be set as its default implementation. Any subsequent attempt
to instantiate the abstract class will return an instance of the
subclass. This replaces elegantly the factory idiom
encountered in other languages.
Finally, the harold.prog.abstract
package can
automatically set the default_implementation
of abstract
classes whenever a concrete subclass is defined, if the abstract
class has no default implementation yet. This is enabled by the autoset_default_implementation
function. This behaviour is disabled by default: since its
consequences might be quite unexpected for someone unaware of this
functionnality, it has to be explicitely enabled.
harold.prog.abstract.abstractable_class
Submodules | |
---|---|
Home | Trees | Index | Help |
|
---|
Generated by Epydoc 2.1 on Mon Dec 18 15:25:58 2006 | http://epydoc.sf.net |