Правильный способ справиться с избыточными аргументами функции - PullRequest
2 голосов
/ 07 февраля 2012

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

class BaseClass:
    def f(self, a, b):
        #do something
        pass

class GeneralCase(BaseClass):
    def f(self, a, b):
        BaseClass.f(self, a, b)
        #do something else

Теперь предположим, что у нас есть особый случай, в котором (среди прочего) один из аргументов функции f является предопределенным и постоянным. Один способ реализовать это состоит в том, чтобы удалить этот аргумент из списка аргументов следующим образом:

class SpecialCase1(GeneralCase):
    def f(self, a):

Pro's: чистый, явный

Con: различная сигнатура метода может вызвать проблемы при использовании объектов разных классов

Вариант 2: установить значение по умолчанию и подтвердить, что оно не изменилось

class SpecialCase2(GeneralCase):
    def f(self, a, b=PREDEFINED_VALUE):
        assert b == PREDEFINED_VALUE
        GeneralCase.f(self, a, PREDEFINED_VALUE)

Pro's: та же подпись

Con's: сбивающий с толку интерфейс: «Почему у нас есть параметр b? Что произойдет, если я его изменю?»

Какой подход вы бы предпочли и почему?

Ответы [ 2 ]

3 голосов
/ 07 февраля 2012

Это вообще не должно быть подтипом (см. Принцип замещения Лискова).

Существует свойство GeneralCase, а именно:

Есть метод f с двумя параметрами ... который делает yadda yadda yadda

Это свойство должно сохраняться для всех подтипов GeneralCase (или типа "утка", всего, что должно крякать, как GeneralCase, независимо от отношений класса). Если он не выполняется, весь код, обрабатывающий такие объекты, должен был бы знать об этом и кодировать вокруг него. Это недопустимое бремя и в значительной степени излишнее.

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

Если вы хотите повторно использовать код, используйте mixins. Если есть код, который может работать как GeneralCase, так и SpecialCase (например, потому что он не использует этот метод), вы можете определить более общий интерфейс, который не включает этот метод (вероятно, неявно, нам не нужно нет interface ключевое слово) и, таким образом, избегает вышеупомянутой проблемы.

0 голосов
/ 07 февраля 2012

Как насчет:

class SpecialCase2(GeneralCase):
    def f(self, a, b):
        GeneralCase.f(self, a, PREDEFINED_VALUE)

Таким образом, специальный случай2 вообще не использует b, а интерфейс остается прежним.

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