0

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?

Aeronaelius
  • 1,291
  • 3
  • 12
  • 31

2 Answers2

1

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.

Jack_of_All_Trades
  • 10,942
  • 18
  • 58
  • 88
  • Thanks this is very instructive. It actually annoys me that in Python, identifiers like `private` and `protected` do not exist. Yes you can prepend with a single `_` or double `_`, however that is more a warning rather than an actual denial. – Aeronaelius Aug 15 '13 at 14:24
  • Exactly, you are right! But python believes in trusting the programmer rather than enforcing the rules. I think that is the python's programming philosophy. Please feel free to accept the answer if it works for you. – Jack_of_All_Trades Aug 15 '13 at 14:25
  • 1
    Well I also somewhat believe in the `Programmer`. However as `Programmer` is a child class of `Human` I would not trust the `Programmer` class too much. – Aeronaelius Aug 15 '13 at 14:48
0

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
tdelaney
  • 73,364
  • 6
  • 83
  • 116