tags:

views:

112

answers:

4

Assuming I have a system of three Classes. The GameClass creates instances of both other classes upon initialization.

class FieldClass:
    def __init__( self ):
        return
    def AnswerAQuestion( self ):    
        return 42

class PlayerClass:
    def __init__( self ):
        return
    def DoMagicHere( self ):
        # Access "AnswerAQuestion" located in the "FieldClass" instance in "GameClass"
        pass

class GameClass:
    def __init__( self ):
        self.Field = FieldClass()
        self.Player = PlayerClass()

What would be the best way of accessing AnswerAQuestion() located in FieldClass from within the instance of PlayerClass?

  • Do I have to pass a reference to the FieldClass instance to PlayerClass?
  • Is there another, better way of solving this? Doing the above would make me have to include an additional variable in PlayerClass to hold the FieldClass instance.
  • Is there a completely different way of managing class relationships in Python?
+2  A: 

I would go with Dependency Injection: instantiate a GameClass with the required FieldClass and PlayerClass in the constructor call etc. (i.e. instead of creating the dependent objects from within GameClass as you are doing at the moment).

class GameClass:
    def __init__( self, fc, pc ):
        self.Field = fc
        self.Player = pc

class PlayerClass:
    def __init__( self, fc ):
        self.fc = fc

    def DoMagicHere( self ):
        # use self.fc
        pass

fc=FieldClass()
pc=PlayerClass(fc)
gc=GameClass(fc, pc)

With DI, you can easily have access to the members you require once the setup phase is completed.

jldupont
+3  A: 

To better understand your class relationships you have to tell us more about your project and what you are trying to accomplish.

One way to reference the instance of FieldClass from PlayerClass in your example is to pass the GameClass instance to the PlayerClass instance:

class PlayerClass:
    def __init__(self, game):
        self.game = game
    def DoMagicHere(self):
        self.game.Field.AnswerAQuestion()

# ...

class GameClass:
    def __init__( self ):
        self.Field = FieldClass()
        self.Player = PlayerClass(self)

Another way is to pass the field variable

class PlayerClass:
    def __init__(self, field):
        self.field = field
    def DoMagicHere(self):
        self.field.AnswerAQuestion()
# ...

class GameClass:
    def __init__( self ):
        self.Field = FieldClass()
        self.Player = PlayerClass(self.Field)

As a side note: you use a peculiar naming scheme. I suggest this:

 class Game:
     def __init__(self):
         self.field = Field()
         self.player = Player(...)

I suggest you read the Python Style Guide before acquiring bad habits.

Otto Allmendinger
Thanks for the info on the naming scheme problem
lamas
+1 for the suggestion to improve the class names.
Joe Koberg
A: 

I would do something like the following, where you pass Game in as a back-reference, allowing you access to the other associated classes. In this way, you could optionally give that player instance a direct relationship to the field.

class FieldClass(object):
    def __init__(self, game):
        self.Game = game
    def AnswerAQuestion(self):    
        return 42

class PlayerClass(object):
    def __init__(self, game):
        self.Game = game
        self.Field = game.Field # Optional
    def DoMagicHere(self):
        self.Game.Field.AnswerAQuestion()
        self.Field.AnswerAQuestion() # Optional

class GameClass(object):
    def __init__(self):
        self.Field = FieldClass(self)
        self.Player = PlayerClass(self)

One side note is that it's good practice now to have all your classes inherit from object rather than to have them standing alone.

Mike Trpcic
+1  A: 

You could provide the context to the child objects, i.e.:

class FieldClass:
  def __init__(self,game):
   self.game = game

class PlayerClass:
  def __init__(self,game):
    self.game = game
  def DoMagicHere(self):
    self.game.Field.AnswerAQuestion()

class GameClass:
  def __init__(self):
    self.Field = FieldClass(self)
    self.Player = PlayerClass(self)

Since the objects know their context they can reach into it and access other objects in the same context.

Geoff Reedy