php
c
python
mysql
xcode
ruby-on-rails
objective-c
multithreading
eclipse
silverlight
html5
perl
algorithm
facebook
tsql
apache
mvc
asp
jsp
That's quite doable, but I don't think you should. Tell the users how to use your class and they should obey. Also, if someone is subclassing he should know how to call the parent's initialization method.
As a proof of concept, here's how it can be done with metaclasses (Python 2.x syntax):
>>> class WhoMovedMyInit(object): class __metaclass__(type): def __init__(self, *args, **kw): super(type,self).__init__(*args, **kw) if self.__init__ is not WhoMovedMyInit.__init__: raise Exception('Dude, I told not to override my __init__') >>> class IAmOk(WhoMovedMyInit): pass >>> class Lol(WhoMovedMyInit): def __init__(self): pass Traceback (most recent call last): File "<pyshell#35>", line 1, in <module> class Lol(WhoMovedMyInit): File "<pyshell#31>", line 6, in __init__ raise Exception('Dude, I told not to override my __init__') Exception: Dude, I told not to override my __init__
You can also replace the subclass __init__ method to one which warns the user or raises an error on "runtime".
__init__
" Whether or not I should or need to do it is a separate discussion :)"
Please, keep that in mind.
But it can be done - when a class is instantiated, not only the syntax is just like a method call - with the class object name followed y a parenthesis - the class itself (which is a Python object), is called - as a callable object.
Calling an object in Python invokes the __call__ magic method in its class. Therefore, instantiating a class, invokes the __call__ method on its metaclass.
__call__
What is inside this __call__ method in the standard metaclass (which is "type") is equivalent to:
def __call__(cls, *args, **kw): self = cls.__new__(cls, *args, **kw) cls.__init__(self, *args, **kw) return self
So, if you write a metaclass, overriding __call__ and suppress the call to __init__ in these, it won't be called at all:
class Meta(type): def __call__(cls, *args, **kw): return cls.__new__(cls, *args, **kw) class NoInit(object): __metaclass__ = Meta def __init__(self): print "Hello!" NoInit()
If you want just to avoid that sublcasses have __init__ instead of not calling it, you can do a much simpler metaclass that would just raise an exception at class instantiation time:
class Meta(type): def __new__(metacls, name, bases, dct): if "__init__" in dct: raise NameError("Classes in this hierarchy should not have an __init__ method") return type.__new__(metacls, name, bases, dct)