472,362 Members | 1,920 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,362 software developers and data experts.

How about "pure virtual methods"?

Hello,

I thought about a new Python feature. Please tell me what you think
about it.

Say you want to write a base class with some unimplemented methods, that
subclasses must implement (or maybe even just declare an interface, with
no methods implemented). Right now, you don't really have a way to do
it. You can leave the methods with a "pass", or raise a
NotImplementedError, but even in the best solution that I know of,
there's now way to check if a subclass has implemented all the required
methods without running it and testing if it works. Another problem with
the existing solutions is that raising NotImplementedError usually means
"This method might be implemented some time", and not "you must
implement this method when you subclass me".

What I suggest is a new class, called notimplemented (you may suggest a
better name). It would get a function in its constructor, and would just
save a reference to it. The trick is that when a new type (a subclass of
the default type object) is created, It will go over all its members and
check to see if any of them is a notimplemented instance. If that is the
case, it would not allow an instantiation of itself.

What I want is that if I have this module:

======================

class BaseClass(object):
def __init__(self):
...

@notimplemented
def save_data(self, filename):
"""This method should save the internal state of the class to
a file named filename.
"""
pass

class RealClass(BaseClass):
def save_data(self, filename):
open(filename).write(self.data)

======================

then if I try to instantiate BaseClass I would get an exception, but
instantiating RealClass will be ok.
Well, what do you say?

Noam Raphael
Jul 18 '05
51 6479
Thanks for your suggestion, but it has several problems which the added
class solves:

* This is a very long code just to write "you must implement this
method". Having a standard way to say that is better.
* You can instantiate the base class, which doesn't make sense.
* You must use testing to check whether a concrete class which you
derived from the base class really implemented all the abstract methods.
Testing is a good thing, but it seems to me that when the code specifies
exactly what should happen, and it doesn't make sense for it not to
happen, there's no point in having a separate test for it.

About the possibility of implementing only a subset of the interface:
You are perfectly welcomed to implement any part of the interface as you
like. Function which use only what you've implemented should work fine
with your classes. But you can't claim your classes to be instances of
the base class - as I see it, subclasses, even in Python, guarantee to
behave like their base classes.

Have a good day,
Noam
Jul 18 '05 #51
"Noam Raphael" <no***@remove.the.dot.myrea.lbox.com> wrote:
Thanks for your suggestion, but it has several problems which the added
class solves:

* This is a very long code just to write "you must implement this
method". Having a standard way to say that is better.
* You can instantiate the base class, which doesn't make sense.
* You must use testing to check whether a concrete class which you
derived from the base class really implemented all the abstract methods.
Testing is a good thing, but it seems to me that when the code specifies
exactly what should happen, and it doesn't make sense for it not to
happen, there's no point in having a separate test for it.

Here's a more refined implementation of the one posted before that
addresses these issues. It defines 'abstractclass', which would be
a nice class decoraror when (and if) class decorators make it into
the language. The extra benefit compared to the MustImplement metaclass
is that it allows a class with no abstract methods to be defined as abstract.
This makes no sense if one defines an abstract class as "a class with one
or more abstract (deferred) methods". Perhaps a more useful and general
definition of an abstract class is "a class that is not allowed to be instantiated".
Deferred methods are one reason for making a class uninstantiable, but it's
not the only one. Sometimes it is useful to define a base class that provides
a default implementation of a full protocol, yet disallow its direct instantiation,
as in the example below.

George

#================================================= ==========
# test_abstract.py

import unittest
from abstract import abstractclass

class AbstractTestCase(unittest.TestCase):

def test_no_abstractmethods(self):
class SomeBase(object):
# This class has no abstract methods; yet calling foo() or bar()
# on an instance of this class would cause infinite recursion.
# Hence it is defined as abstract, and its concrete subclasses
# should override at least one of (foo,bar) in a way that breaks
# the recursion.
def __init__(self, x):
self._x = x
def foo(self, y):
return self.bar(self._x + y)
def bar(self, y):
return self.foo(self._x - y)
SomeBase = abstractclass(SomeBase)

class Derived(SomeBase):
def __init__(self,x):
SomeBase.__init__(self,x)
def foo(self,y):
return self._x * y

self.assertRaises(NotImplementedError, SomeBase, 5)
self.assertEquals(Derived(5).bar(2), 15)

if __name__ == '__main__':
unittest.main()

#================================================= ==========
# abstract.py

import inspect

__all__ = ["abstractclass", "abstractmethod", "AbstractCheckMeta"]
def abstractclass(cls):
'''Make a class abstract.

Example::
# hopefully class decorators will be supported in python 2.x
# for some x, x>4
#@abstractclass
class SomeBase(object):
@abstractmethod
def function(self):
"""Implement me"""
# the only way as of python 2.4
SomeBase = abstractclass(SomeBase)

@param cls: A new-style class object.
@return: A surrogate of C{cls} that behaves as abstract. The returned
class raises NotImplementedError if attempted to be instantiated
directly; still its subclasses may call its __init__. A subclass of
the returned class is also abstract if it has one or more abstract
methods, or if it is also explicitly decorated by this function. A
method is declared abstract by being assigned to NotImplemented (or
decorated by L{abstractmethod}).
@raise TypeError: If there is a metaclass conflict between C{type(cls)}
and L{AbstractCheckMeta}, or if C{cls} has an C{__abstractmethods__}
attribute.
'''
# check if cls has AbstractCheckMeta (or a subtype) for metaclass
metaclass = type(cls)
if not issubclass(metaclass, AbstractCheckMeta):
# it doesn't; try to make AbstractCheckMeta its metaclass by
# inheriting from _AbstractCheck
cls = metaclass(cls.__name__, (_AbstractCheck,) + cls.__bases__,
dict(cls.__dict__))
# replace __init__ with a proxy ensuring that __init__ is called by a
# subclass (but not directly)
old_init = getattr(cls,'__init__',None)
def new_init(self,*args,**kwds):
if self.__class__ is cls:
raise NotImplementedError("%s is an abstract class" % cls.__name__)
if old_init is not None:
old_init(self,*args,**kwds)
setattr(cls,'__init__',new_init)
return cls
def abstractmethod(function):
'''A method decorator for those who prefer the parameters declared.'''
return NotImplemented
class AbstractCheckMeta(type):
'''A metaclass to detect instantiation of abstract classes.'''

def __init__(cls, name, bases, dict):
if '__abstractmethods__' in cls.__dict__:
raise TypeError("'__abstractmethods__' is already defined in "
"class '%s': %s" % (cls.__name__,
cls.__dict__['__abstractmethods__']))
type.__init__(cls, name, bases, dict)
cls.__abstractmethods__ = [name for name, value in
inspect.getmembers(cls)
if value is NotImplemented]

def __call__(cls, *args, **kwargs):
if cls.__abstractmethods__:
raise NotImplementedError(
"Class '%s' cannot be instantiated: Methods %s are abstract."
% (cls.__name__,", ".join(map(repr,cls.__abstractmethods__))))
return type.__call__(cls, *args, **kwargs)
class _AbstractCheck(object):
'''
A class to stick anywhere in an inheritance chain to make its
descendants being checked for whether they are abstract.
'''
__metaclass__ = AbstractCheckMeta
Jul 18 '05 #52

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: cppaddict | last post by:
Hi, I know that it is illegal in C++ to have a static pure virtual method, but it seems something like this would be useful when the following 2 conditions hold: 1. You know that every one...
175
by: Ken Brady | last post by:
I'm on a team building some class libraries to be used by many other projects. Some members of our team insist that "All public methods should be virtual" just in case "anything needs to be...
0
by: AndyPSV | last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and...
0
by: Arjunsri | last post by:
I have a Redshift database that I need to use as an import data source. I have configured the DSN connection using the server, port, database, and credentials and received a successful connection...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific technical details, Gmail likely implements measures...
0
by: Carina712 | last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand. Background colors can be used to highlight important...
0
BLUEPANDA
by: BLUEPANDA | last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS starter kit that's not only easy to use but also...
0
by: Rahul1995seven | last post by:
Introduction: In the realm of programming languages, Python has emerged as a powerhouse. With its simplicity, versatility, and robustness, Python has gained popularity among beginners and experts...
1
by: Ricardo de Mila | last post by:
Dear people, good afternoon... I have a form in msAccess with lots of controls and a specific routine must be triggered if the mouse_down event happens in any control. Than I need to discover what...
0
by: Johno34 | last post by:
I have this click event on my form. It speaks to a Datasheet Subform Private Sub Command260_Click() Dim r As DAO.Recordset Set r = Form_frmABCD.Form.RecordsetClone r.MoveFirst Do If...
1
by: ezappsrUS | last post by:
Hi, I wonder if someone knows where I am going wrong below. I have a continuous form and two labels where only one would be visible depending on the checkbox being checked or not. Below is the...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.