views:

67

answers:

1

I'm writing a simulation in Python for a dice game, and am trying to find the best way to handle the following situation in an Object Oriented manner.

I have a Dice class that handles rolling the dice and reporting things about the dice. This class's methods include a roll() method which modifies the dice values, and various reporting methods that describe the state of the dice, such as have_n_of_a_kind(), is_scoring_combination(), and get_roll_value().

There are two classes which make use of this Dice class. The Player, controlled directly by a human, is untrusted to always make legal moves. There is also a Turn class which enforces the rules of the game.

So then, both the Player and Turn class need to be able to ask the Dice about its values by calling the state describing methods, but the Player cannot be allowed to directly call the roll() method, because the human Player might roll when it is not supposed to.

Is there a good way for me to allow the Turn class to call a Dice object's roll() method but not allow a Player to do so?

+1  A: 

Have the Player ask the Turn to roll, by calling e.g. turn.roll_dice(). The Turn can then decide whether to roll the dice or e.g. to raise NotYourTurnError.

You can't prevent the Player class directly calling die.roll(), although you can make roll private by renaming it __roll. However, since I assume the player is controlling the die via some sort of (G?) UI, you can simply not include any way of telling the die to roll in said interface.

In general, you can't hide methods like this from arbitrary Python code with any degree of security; Python is so powerful that you'll almost certainly be able to find a way around the protection. Instead, you make them protected (_foo) or private (__foo) and assume that people who call them know what they're doing.

katrielalex
Single and double underscoring do not directly correspond to the `protected` and `private` accessibility modifiers in other languages as this post seems to suggest. The pythonic thing to do would be considering using single underscoring (`_foo`) to *indicate* ~privateness~ but note that with double underscoring (even when it does some name mangling) Python does not enforce privateness in any way (as correctly stated), so using `__foo` is generally advised against.
ChristopheD
ChristopheD is entirely correct here. It's axiomatic that as soon as you try to do any reflective programming in python, you'll get burned by double-underscore name mangling. If that doesn't mean anything to you, don't worry about it, but don't use __foo.
Russell Borogove