2015-03-24 2 views
2

Я относительно новичок в ООП и, безусловно, все еще учась. Я хотел бы знать, что является наилучшей практикой при работе с двумя классами, такими как:Состав: Должен ли я напрямую обращаться к методам «внутреннего объекта»?

(У меня есть обратная конструкция двигателя статистики старой компьютерной игры, но я думаю, что вопрос не имеет значения для моего вопроса)

class Step(object): 
    def __init__(self): 
     self.input = 'G' 

    ...more attributes... 

    def reset_input(self): 
     ''' Reset input to None. ''' 
     self.input = None 
     print '* Input reset.' 

     ... more methods ... 

Тогда у меня есть класс игрока, который является основным объектом для контроля (по крайней мере, в моей конструкции):

class Player(object): 
    ''' Represents a player. Accepts initial stats.''' 
    def __init__(self, step= 250, off= 13, dng= 50000, dist= 128, d_inc= 113): 
     self.route = [] 
     self.step = Step(step=step, off=off, dng=dng, dist=dist, d_inc=d_inc) 
     self.original = copy.copy(self.step) 

Как вы можете видеть, плеер содержит Шаг объект, который представляет собой следующий шаг.

Я обнаружил, что иногда хочу получить доступ к методу из этого класса Step. В этом случае, лучше добавить обертку игроку, такие как:

(Если я хочу, чтобы получить доступ к reset_input()):

class Player(object): 
    ... 
    def reset_input(self): 
     self.step.reset_input() 

Тогда для игрока, чтобы сбросить значение ввода:

p = Player() 
p.reset_input() 

Или было бы лучше практика, чтобы получить доступ к reset_input() непосредственно:

p = Player() 
p.step.reset_input() 

Кажется, что добавление обертки - это только , дублирующий код. Это также раздражает, поскольку мне нужен доступ к нескольким методам Step.

Итак, при использовании композиции (Я думаю, что это правильный термин), является ли хорошей практикой прямой доступ к методам «внутренних» объектов?

+1

Лучше для объекта 'Player' сбросить входное значение. Дополнительный уровень косвенности позволит вам легко изменить, как объекты 'Player' будут делать вещи в будущем. Это называется скрытием информации или инкапсуляцией. – martineau

ответ

3

Я считаю, вы должны применить дополнительный слой абстракции в ООП, если:

  1. вы предвидеть себя обновление кода позже; и
  2. код будет использоваться во многих местах.

В этом случае, скажем, вы идете с этим методом:

def reset_input(self): 
    self.step.reset_input() 

, а затем вы называете его в нескольких местах в вашем коде. Позже вы решите, что хотите сделать действие x() перед всеми вашими звонками до reset_input, передать необязательный параметр y по номеру reset_input и выполнить действие z() после этого. Тогда это тривиальное обновить метод следующим образом:

def reset_input(self): 
    self.x() 
    self.step.reset_input(self.y) 
    self.z() 

И код будет изменен везде с помощью всего нескольких нажатий клавиш. Представьте себе кошмар, который у вас был бы на руках, если бы вам пришлось обновлять все вызовы в нескольких местах, потому что вы не использовали функцию обертки.

Вы должны применить обертку, если вы действительно предвидите себя , используя оболочку, чтобы применить изменения к вашему коду. Это упростит работу вашего кода. Как указано в комментариях, эта концепция известна как инкапсуляция ; он позволяет использовать интерфейс, который скрывает детали реализации, так что вы можете легко обновить реализацию в любое время, и это изменит код повсеместно очень простым способом.

1

Это всегда компромисс. Посмотрите на Law of Demeter. Он описывает вашу ситуацию, а также плюсы и минусы различных решений.

Смежные вопросы