Python OOP - Классовые отношения - PullRequest
8 голосов
/ 24 февраля 2010

Предполагая, что у меня есть система из трех классов. GameClass создает экземпляры обоих других классов при инициализации.

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()

Каков наилучший способ доступа к AnswerAQuestion(), расположенному в FieldClass из экземпляра PlayerClass?

  • Нужно ли передавать ссылку на экземпляр FieldClass на PlayerClass?
  • Есть ли другой, лучший способ решения этой проблемы? Выполнение вышеизложенного заставило бы меня включить в PlayerClass дополнительную переменную для хранения экземпляра FieldClass.
  • Есть ли совсем другой способ управления отношениями классов в Python?

Ответы [ 4 ]

6 голосов
/ 24 февраля 2010

Я бы пошел с Внедрение зависимости : создать экземпляр GameClass с необходимыми FieldClass и PlayerClass в вызове конструктора и т. Д. (Т. Е. Вместо создания зависимых объектов из GameClass как вы делаете в данный момент).

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)

С DI вы можете легко получить доступ к нужным вам участникам после завершения фазы установки.

4 голосов
/ 24 февраля 2010

Чтобы лучше понять ваши классовые отношения, вы должны рассказать нам больше о вашем проекте и о том, что вы пытаетесь достичь.

Один из способов ссылки на экземпляр из FieldClass из PlayerClass в вашем примере - передать экземпляр GameClass в PlayerClass:

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)

Другой способ - передать переменную field

.
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)

В качестве примечания: вы используете особую схему именования. Я предлагаю это:

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

Я предлагаю вам прочитать Руководство по стилю Python , прежде чем приобретать вредные привычки.

1 голос
/ 24 февраля 2010

Вы могли бы предоставить контекст дочерним объектам, т.е.:

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)

Поскольку объекты знают свой контекст, они могут проникнуть в него и получить доступ к другим объектам в том же контексте.

0 голосов
/ 24 февраля 2010

Я бы сделал что-то вроде следующего, где вы передаете Game в качестве обратной ссылки, позволяя вам получить доступ к другим связанным классам. Таким образом, вы можете при желании дать этому экземпляру игрока прямую связь с полем.

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)

Заметим, что сейчас хорошая практика, когда все ваши классы наследуются от object, а не в одиночестве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...