Aeronaelius
Aeronaelius

Reputation: 1331

How to deny users to create an instance of a parent object in Python

Let's say I create a parent class named Ball. As child classes I then continue to create Basketball, Baseball and Tennisbal. However I would not like my users to ever create an instance of Ball because it is not specific enough. I would like to force users to directly create a specific ball by creating an instance of any of the child classes. How can I deny access to the parent class and maintain the child classes accessible?

Upvotes: 0

Views: 261

Answers (2)

tdelaney
tdelaney

Reputation: 77337

Have Ball.__init__() raise NotImplementedError.

(edit)

The goal with this suggestion is to keep it simple. If you need the init, you can have your base class check for something all implementors must have or just create a flag to tell you what is going on:

class A(object):
    _abstract = True

    def __init__(self):
        if self._abstract:
            raise NotImplementedError("Cannot instantiate abstract base class")

class B(A):
    _abstract = False

Upvotes: 0

Jack_of_All_Trades
Jack_of_All_Trades

Reputation: 11468

Basically, you can't in strict sense. Every classes and methods in python are public so it is not possible. You can do some mangling but still it is not going to stop if somebody is thinking of using it.

By convention, most python programmer will prefix the method or attribute with _ to denote the internal method. But nothing is going to stop it.

An example of mangling (excerpt from a Python 3 Object Oriented Programming Using Python):

class SecretString:
  '''A not-at-all secure way to store a secret string.'''

    def __init__(self, plain_string, pass_phrase):
       self.__plain_string = plain_string
       self.__pass_phrase = pass_phrase

def decrypt(self, pass_phrase):
    '''Only show the string if the pass_phrase is correct.'''
      if pass_phrase == self.__pass_phrase:
     return self.__plain_string
     else:
      return ''

Now let's try this:

>>> secret_string = SecretString("ACME: Top Secret", "antwerp")
>>> print(secret_string.decrypt("antwerp"))
ACME: Top Secret
>>> print(secret_string.__plain_text)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError:

WOW! it worked.

Now, this:

>>> print(secret_string._SecretString__plain_string)
ACME: Top Secret

No it failed.

The above is one example of name mangling which you can use at the best sense.

Upvotes: 1

Related Questions