Hi Henning,

This feature was implemented by @tonyroberts in 2013 and is tested in CI with test_subclass.py file.

According to these tests, the missing piece in your code is defining explicitly __namespace__ on the .NET class derived in Python:

In [11]: class StringDoor1(Door):
   ....:     __namespace__ = "PythonBaseClass"
   ....:     def __init__(self):
   ....:         self.status = "closed"
   ....:
   ....:     def IsOpen(self):
   ....:         print "StringDoor.IsOpen()"
   ....:         return self.status == "open"
   ....:
   ....:     def Toggle(self):
   ....:         print "StringDoor.Toggle()"
   ....:         if self.status == "open":
   ....:             self.status = "closed"
   ....:         else:
   ....:             self.status = "open"

In [12]: d = StringDoor1()

In [13]: d.status
Out[13]: 'closed'

In [14]: d.Open()
StringDoor.IsOpen()
StringDoor.Toggle()

In [15]: d.status
Out[15]: 'open'



Thanks,
Denis

On Mon, Sep 26, 2016 at 9:19 AM, Henning Moeller <HMoeller@comprion.com> wrote:

Hi Denis,

 

Thanks for your fast response. Sounds completely reasonable to me. And this has not been too much of an issue for me.

 

I got rid of the abstract base class simply by providing an “empty” implementation and using a non-abstract base class. No need for meta classes any more. This way, I got rid of error messages. Great!

 

Unfortunately, there seem to be an issue when calling a virtual method inside the C# implementation. Even when overriding this virtual method in Python, it’s still the base class’ implementation which is called.

 

See the new simple base class defined in C#:

 

namespace PythonBaseClass

{

    using System;

 

    public class Door

    {

        public virtual void Open()

        {

            if (!IsOpen())

                Toggle();

        }

 

        public virtual void Close()

        {

            if (IsOpen())

                Toggle();

        }

 

        public virtual bool IsOpen()

        {

            Console.WriteLine("Door.IsOpen()");

            return false;

        }

 

        public virtual void Toggle()

        {

            Console.WriteLine("Door.Toggle()");

        }

    }

}

 

The consuming Python code now looks like this:

 

import clr

from PythonBaseClass import Door

 

class StringDoor(Door):

    def __init__(self):

        self.status = "closed"

 

    def IsOpen(self):

        print "StringDoor.IsOpen()"

        return self.status == "open"

 

    def Toggle(self):

        print "StringDoor.Toggle()"

        if self.status == "open":

            self.status = "closed"

        else:

            self.status = "open"

 

But the output does not look like expected:

 

Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 32 bit (Intel)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> from PythonInheritedClass import StringDoor

>>> d = StringDoor()

>>> d.status

'closed'

>>> d.Open()

Door.IsOpen()

Door.Toggle()

>>> d.status

'closed'

>>> 

 

From my understanding, the output should rather read “StringDoor.<something>()” instead of “Door.<something>()”. Obviously, only the base implementation is called but the overridden methods are ignored.

 

Also a limitation of inheriting C# classes in pythonnet?

 

BR,

 

Henning

 

From: PythonDotNet [mailto:pythondotnet-bounces+hmoeller=comprion.com@python.org] On Behalf Of Denis Akhiyarov
Sent: Donnerstag, 22. September 2016 19:38
To: A list for users and developers of Python for .NET <pythondotnet@python.org>
Subject: Re: [Python.NET] Inheriting from abstract .NET class

 

You are not a "Python n00b" based on metaclass usage!

 

My recommendation is to keep simple integration layer between CPython and .NET, hence metaclasses were/are not supported.

 

But contributions are welcome! Although I expect this to be a tremendous undertaking based on reviewing multiple sources.

 

Note that metaclass is a very different low-level concept from higher-level abstract classes in .NET, hence direct mapping (e.g. `.register()` ) is not feasible.

 

Thanks,

Denis

 

On Thu, Sep 22, 2016 at 10:04 AM, Henning Moeller <HMoeller@comprion.com> wrote:

Hello out there,

 

I’m trying to inherit from an abstract .NET base class in Python (2.7). I’m a Python n00b but from what I understood…

 

Here’s what I managed to do in Python only and which works fine:

 

[File: room.py] -------

import abc

 

class Room(object):

    def __init__(self, door):

        self.door = door

 

    def open(self):

        self.door.open()

 

    def close(self):

        self.door.close()

 

    def is_open(self):

        return self.door.is_open()

       

class Door(object):

    __metaclass__ = abc.ABCMeta

   

    def open(self):

        if not self.is_open():

            self.toggle()

 

    def close(self):

        if self.is_open():

            self.toggle()

 

    @abc.abstractmethod

    def is_open(self):

        pass

 

    @abc.abstractmethod

    def toggle(self):

        pass

   

class StringDoor(Door):

    def __init__(self):

        self.status = "closed"

       

    def is_open(self):

        return self.status == "open"

       

    def toggle(self):

        if self.status == "open":

            self.status = "closed"

        else:

            self.status = "open"

 

class BooleanDoor(Door):

    def __init__(self):

        self.status = True

 

    def is_open(self):

        return self.status

       

    def toggle(self):

        self.status = not (self.status)

 

Door.register(StringDoor)

Door.register(BooleanDoor)

-------

       

Now, all I did was to replace the abstract base class Door by a C# representation:

 

[File: PythonAbstractBaseClass.dll] -------

namespace PythonAbstractBaseClass

{

    public abstract class Door

    {

        public virtual void Open()

        {

            if (!IsOpen())

                Toggle();

        }

 

        public virtual void Close()

        {

            if (IsOpen())

                Toggle();

        }

 

        public abstract bool IsOpen();

        public abstract void Toggle();

    }

}

-------

 

Removing Door from the Python part and importing it from the .NET assembly instead, I end up with this:

 

[File: room2.py] -------

import clr

import abc

from PythonAbstractBaseClass import Door

 

class Room(object):

    def __init__(self, door):

        self.door = door

 

    def open(self):

        self.door.open()

 

    def close(self):

        self.door.close()

 

    def is_open(self):

        return self.door.is_open()

       

class StringDoor(Door):

    def __init__(self):

        self.status = "closed"

       

    def is_open(self):

        return self.status == "open"

       

    def toggle(self):

        if self.status == "open":

            self.status = "closed"

        else:

            self.status = "open"

 

class BooleanDoor(Door):

    def __init__(self):

        self.status = True

 

    def is_open(self):

        return self.status

       

    def toggle(self):

        self.status = not (self.status)

 

Door.register(StringDoor)

Door.register(BooleanDoor)

-------

       

But this fails with the following error message:

 

    Door.register(StringDoor)

AttributeError: type object 'Door' has no attribute 'register'

 

From what I understood about abc.ABCMeta, this metaclass contributes the ‘register’ method. It seems that abstract C# classes do not come with the same metaclass. They instead come with metaclass “CLR Metatype” which obviously does not provide ‘register’.

 

But if I drop the call to ‘register’, on instantiating one of the derived classes, I receive the error message

 

    sdoor = StringDoor()

TypeError: cannot instantiate abstract class

 

Is there a way to inherit from an abstract .NET class or is this is missing feature?

 

Thanks in advance,

 

Henning

 


_________________________________________________
Python.NET mailing list - PythonDotNet@python.org
https://mail.python.org/mailman/listinfo/pythondotnet

 


_________________________________________________
Python.NET mailing list - PythonDotNet@python.org
https://mail.python.org/mailman/listinfo/pythondotnet