Ugh. Usually, multiple inheritance from extension types in Python (and
hence Cython) is prohibited because the base types have different
layouts, e.g.
class C(Integer, RealDoubleElement): pass
...:
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
TypeError: Error when calling the metaclass bases
multiple bases have instance lay-out conflict
Here the class layouts are compatible, so no error on construction,
but the vtables are not. The simple solution is to simply disallow
such inheritance, supporting it dynamically would be tricky or
expensive (or both).
On Sat, Mar 9, 2013 at 12:05 AM, Simon King <
simon...@uni-jena.de> wrote:
> Hi!
>
> Currently, I try to make homsets and morphisms compliant with what one
> would usually do when implementing parents and elements---in particular,
> the default __mul__ and __add__ should do something meaningful and should
> thus not be overridden. In particular, one would implement addition in
> subclasses by providing a method _add_, not __add__.
>
> But this implies a subtle problem, in
> sage.homology.chain_complex_morphism.ChainComplexMorphism.
>
> I guess one would like to define it as follows,
> class ChainComplexMorphism(Morphism, ModuleElement)
> because it is a morphism, on the one hand, but a module element, on the
> other hand.
>
> Both Morphism and ModuleElement are extension classes with their own cdef
> attributes/methods, but it *is* possible to inherit from both (Python
> does not throw an error, i.e., it does not complain about incompatible
> layouts).
>
> If one makes ChainComplexMorphism use the __add__ method inherited from
> ModuleElement, then eventually the line
> return (<ModuleElement>left)._add_(<ModuleElement>right)
> is executed. But "(<ModuleElement>left)._add_" returns a totally
> different cdef method, namely "(<Map>left)._update_slots"! Example:
>
> sage: cython("""
> ....: from sage.categories.map cimport Map
> ....: from sage.structure.element cimport ModuleElement
> ....: def test(a):
> ....: return <void*>((<ModuleElement>a)._add_) == <void *>((<Map>a)._update_slots)
> ....: """)
> sage: from sage.categories.map import Map
> sage: class C(Map, ModuleElement): pass
> ....:
> sage: test(a)
> True
> sage: a._add_(a)
> Traceback (most recent call last):
> ...
> ... in sage.structure.element.ModuleElement._add_ (sage/structure/element.c:9801)()
> ... in sage.categories.map.Map._update_slots (sage/categories/map.c:2633)()
> TypeError: 'C' object has no attribute '__getitem__'
>
> So, _add_ can not be accessed, and in particular one can not use the
> default __add__ (which is essential for using the coercion model) on a
> class that inherits from both Map and ModuleElement.
>
> Do you see a work around?
>
> I asked this question on the cython-users list, too (sorry for those who
> read both), but I think it is as much a question about sage than a
> question about cython.
>
> Best regards,
> Simon
>
>
> --
> You received this message because you are subscribed to the Google Groups "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to
sage-devel+...@googlegroups.com.
> To post to this group, send email to
sage-...@googlegroups.com.
> Visit this group at
http://groups.google.com/group/sage-devel?hl=en.
> For more options, visit
https://groups.google.com/groups/opt_out.
>
>