Есть ли практическое правило, когда кодировать статический метод против метода экземпляра? - PullRequest
7 голосов
/ 24 января 2009

Я изучаю Java (и ООП), и, хотя это может не иметь значения для того места, где я сейчас нахожусь, мне было интересно, может ли SO поделиться некоторыми распространенными ошибками или хорошими методами проектирования.

Ответы [ 13 ]

14 голосов
/ 24 января 2009

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

9 голосов
/ 24 января 2009

Я не думаю, что какой-либо из ответов доходит до сути ОО причины выбора того или иного. Конечно, используйте метод экземпляра, когда вам нужно иметь дело с членами экземпляра, но вы можете сделать все ваши члены публичными, а затем кодировать статический метод, который принимает экземпляр класса в качестве аргумента. Привет С.

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

Известными исключениями, которые приходят на ум, являются паттерны Factory Method и Singleton (экономно использующие). Проявляйте осторожность, когда у вас возникает желание написать «вспомогательный» класс, поскольку оттуда это скользкий уклон в процедурном программировании.

2 голосов
/ 24 января 2009

Если реализация метода может быть полностью выражена в виде открытого интерфейса (без понижения рейтинга) вашего класса, то это может быть хорошим кандидатом для статического «служебного» метода. Это позволяет вам поддерживать минимальный интерфейс, в то же время предоставляя удобные методы, которые клиенты кода могут использовать очень часто. Как объясняет Скотт Мейерс, , этот подход поощряет инкапсуляцию, сводя к минимуму объем кода, на который влияет изменение внутренней реализации класса. Вот еще одна интересная статья Херба Саттера, которая разбирает std :: basic_string, решая, какие методы должны быть членами, а какие - нет.

В таких языках, как Java или C ++, я признаю, что статические методы делают код менее элегантным, поэтому компромисс все еще остается. В C # методы расширения могут дать вам лучшее из обоих миров.

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

1 голос
/ 24 января 2009

Выбор по умолчанию должен быть методом экземпляра.

1 голос
/ 24 января 2009

Если вы сохраняете состояние (значение) объекта и метод используется для доступа или изменения состояния, тогда вам следует использовать метод экземпляра.

Даже если метод не изменяет состояние (служебная функция), я бы порекомендовал вам использовать метод экземпляра. Главным образом потому, что таким образом вы можете иметь подкласс, который выполняет другое действие.

В остальном вы можете использовать статический метод.

:)

1 голос
/ 24 января 2009

Мое эмпирическое правило таково: если метод выполняет что-либо, связанное с конкретным экземпляром класса, независимо от того, нужно ли ему использовать переменные экземпляра класса. Если вы можете рассмотреть ситуацию, когда вам может понадобиться использовать определенный метод, не обязательно ссылаясь на экземпляр класса, тогда этот метод должен быть статическим (класс). Если этому методу также необходимо использовать переменные экземпляра в определенных случаях, то, вероятно, лучше создать отдельный метод экземпляра, который вызывает статический метод и передает переменные экземпляра. С точки зрения производительности, я полагаю, что разница незначительна (по крайней мере, в .NET, хотя я думаю, что она будет очень похожа на Java).

0 голосов
/ 12 сентября 2009

Мой статический метод всегда один из следующих:

  1. Частные "вспомогательные" методы, которые оценивают формулу, полезную только для этого класса.
  2. Заводские методы (Foo.getInstance() и т. Д.)
  3. В "служебном" классе, который является окончательным, имеет закрытый конструктор и не содержит ничего, кроме открытых статических методов (например, com.google.common.collect.Maps)

Я не буду делать метод статичным только потому, что он не ссылается ни на какие переменные экземпляра.

0 голосов
/ 24 января 2009

проблема со статическими методами заключается в том, что вы нарушаете один из основных объектно-ориентированных принципов, поскольку вы связаны с реализацией. Вы хотите поддержать принцип открытого закрытия, и ваш класс должен реализовать интерфейс, который описывает зависимость (в поведенческом абстрактном смысле), и затем ваши классы зависят от этого интерфейса. Гораздо проще продвинуться после этого момента, продвигаясь вперед. ..

0 голосов
/ 24 января 2009

ИМХО, если вы можете сделать его статическим методом (без необходимости изменять его структуру), тогда сделайте его статическим методом. Это быстрее и проще.

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

Как правило, вам не следует добавлять функциональность, как только вы представляете себе использование в один прекрасный день (таким образом, безумие), вы должны добавлять только те функции, которые вам действительно нужны.

Для более подробного объяснения ...

http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It

http://c2.com/xp/YouArentGonnaNeedIt.html

0 голосов
/ 24 января 2009

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

Статические ссылки запекаются в вашей реализации и не могут быть изменены. Я считаю статические полезными для коротких служебных методов. Если содержимое вашего статического метода очень велико, вы можете подумать о том, чтобы разделить ответственность на один или несколько отдельных объектов и позволить им взаимодействовать с клиентским кодом как экземплярами объекта.

...