Есть ли какие-либо недостатки у статических методов?

Узнал от(значительно) более опытного коллеги, что использование статических методов считается нарушением принципов ООП. Хотелось бы уточнить, о каких именно принципах идёт речь и имеют ли они под собой какой-то рациональный фундамент.

Условная ситуация:
public class ListToStringConverter
{
public string ListToString(List<MyObject> obj)
{
var a="";
...
...
return a;
}
}

Соответственно, я могу сделать метод и сам класс статическим(и иметь красивый код) или не делать(и каждый раз создавать экземпляр класса, чтобы вызвать метод) .
Что будет занимать больше памяти и как вообще в обоих случаях будет работать сборщик мусора?
Что будет работать быстрее?
Есть ли у статического варианта какие-то подводные камни, например, при вызове из нескольких потоков?
  • Вопрос задан
  • 6218 просмотров
Решения вопроса 1
@D3lphi
Значит так, берем толстую тетрадь, ручку и пишем фразу "Статические методы не имеют отношения к ООП" до тех пор, пока не запомним это на всю жизнь.
Суть объектно ориентированного программирование, как понятно из названия, заключается в том, что должен существовать объект. Статика существует не в контексте объекта, а в контексте класса! Из этого вытекает то, что на протяжении всего жизненного цикла вашего кода будет существовать лишь одно глобальное состояние статических членов класса.

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

Есть ли у статического варианта какие-то подводные камни

Большое количество. При чем, не таких уж и подводных. Из-за того, что статика глобальна, она плохо поддается тестированию, ее нельзя замокать. Глобальное состояние плохо поддается отладке. Отсутствует возможность подменить реализацию, так как это позволяют сделать объекты.
Ответ написан
Пригласить эксперта
Ответы на вопрос 9
qonand
@qonand
Software Engineer
Узнал от(значительно) более опытного коллеги, что использование статических методов считается нарушением принципов ООП.

Ну как бы основной принцип ООП построение программного кода на основе объектов. Что такое объект? это некая сущность имеющая состояние и имеющая методы работающие с этим состоянием. Любые статические компоненты - относятся не к объектам а к классу.

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

В некоторых случаях такой подход уместен, например при создании классов-хелперов. В остальных случаях нет.

Что будет занимать больше памяти и как вообще в обоих случаях будет работать сборщик мусора?

Какая разница? Это экономия на спичках в которой нет смысла

Что будет работать быстрее?

Все зависит от компилятора

Есть ли у статического варианта какие-то подводные камни, например, при вызове из нескольких потоков?

Статический метод от глобальной функции отличается только тем что он привязан к классу. Делайте выводы...
Ответ написан
mindtester
@mindtester Куратор тега C#
https://www.youtube.com/watch?v=Dn9_ogWhk9s
в C# есть очень элегантный механизм расширений возможностей существующих обьектов, он так и называется - расширения
https://docs.microsoft.com/ru-ru/dotnet/csharp/pro...
https://metanit.com/sharp/tutorial/3.18.php

но реализуется он только статическими методами, и только в статических классах

следующий пример - фабрики классов, так вот в C#, наиболее естественным образом, фабрики реализуются именно статическими методами

всем этим приемам есть свое место и время, просто надо в этом разобраться

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

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

Есть ли у статического варианта какие-то подводные камни, например, при вызове из нескольких потоков?
у методов может и нет, зависит о того к чему они обращаются? если вызываете другие потокобезопасные методы (библиотечных классов) + изучите и будете применять потокобезопасные алгоритмы - какие могут быть проблемы? (пример - расширения LINQ, который вообще почти полностью на расширениях то и построен (то есть в основном на статических методах))

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

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

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

Если возникает необходимость сделать статические методы с логикой посерьезней фильтра списка, например, доступ к БД, то есть пара вариантов в этом случае. Первый, сделать синглтон, если хотите, чтобы была одна точка входа для доступа к БД и Вы хотите эту точку и попытки получения данных из БД контролировать.
Второй, это иньекция зависимостей и контейнеры для них, всевозможные IoC. В настройках IoC указываете, что выдавать единственный экземпляр и он по сути сам станет singlton, фабрика контейнера не будет на каждое обращение создавать новый экземпляр.

Лично я статическими методами и даже полями пользуюсь. Иметь хелперы, это удобно, но, конечно, без фанатизма.
Ответ написан
Комментировать
usdglander
@usdglander
Yipee-ki-yay
В статические методы выносят либо упрощённый конструктор, либо небольшие функции не зависящие от конкретного объекта и его состояния (Например метод складывающий два переданных ему числа будет возвращать один и тот же результат не зависимо от состояния объекта).
Ответ написан
Комментировать
@mletov
Я, например, нажегся в ASP.NET.
Разные юзеры генерили отчеты, у отчета были статические свойства. Я полагал, что значение свойств у каждого отчета для каждого юзера будет разное, ан нет. IIS, судя по всему, выдавал разным юзерам отчет из одного потока. Пришлось переписать, создавать отчет экземпляром класса и присваивать ему свойства.

Статические методы использую, например, чтобы преобразовать/форматировать что-то во что-то, если алгоритм преобразования достаточно хитрый. В статические свойства складываю константы или настройки какие-нибудь.
Ответ написан
Комментировать
Therapyx
@Therapyx
Data Science
судя по комментариям и твоей "цели", я бы посоветовал использовать Singleton или Multiton (см. Design Patterns) - один из самых простейших причем.
банальный пример - реализация подключения к базе данных и неким постом с программой, где множество инстанций требует именно этого функционала.

Хотя скорее всего есть и более элегантные решения в с# :D
Ответ написан
Комментировать
devalone
@devalone
̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻
Я бы посомневался в опытности коллеги. Не нарушают статические методы принципы ООП, а использовать нужно тогда, когда не нужен экземпляр класса, т.е. не нужно хранить состояние объекта, один из частых вариантов использования - singletone, либо какие-то типичные функции вроде sqrt, abs и т.д. используя класс как пространство имён
Ответ написан
Комментировать
Как уже говорили выше, статические методы относятся к классу в целом, а не к конкретному объекту. Что касается производительности: если сравнивать обычный метод внутри класса и статический, то статический будет работать быстрее из-за того, что не тратятся ресурсы на инициализацию конструктора. Но, сами понимаете, обычно это никакого существенного буста в производительности не даёт.
Ответ написан
Комментировать
@vanyamba-electronics
Приведённый пример довольно плохо иллюстрирует суть вопроса, в силу того, что является примером неграмотного дизайна.
У вас есть класс - форматированная строка. Назовём его FormattedString.
Далее мы определяем операторы для разных типов. В данном случае у нас есть тип - какой-то список чего-то. В ООП не может быть класса MyList. Это дизайн в стиле GUI от Билла Гейтса, а не ООП от Гради Буча и Бьорна Страуструпа.
Поэтому у нас тип, назовём его ListOfFoo - это список чего-то конкретного, в данном случае список Foo.
И мы хотим добавить метод преобразования списка Foo в форматированную строку.
Для этого мы добавляем в класс FormattedString оператор присваивания для класса ListOfFoo:
class FormattedString
{
public:
    operator = (const ListOfFoo& src);
};

Но случаются ситуации, когда в приложении существует одна и только одна инстанция объекта. Например, объект theApp.
Как, например, получить ссылку на этот объект. Не передавать же его по иерархии объектов.
Для этого удобно определить статический метод Application::getApp(), который будет возвращать ссылку на инстанцию объекта-приложения.
Итак, сформулируем правило. Программа - это процессор. Объекты - это то, что она создаёт в оперативной памяти, статические объекты - это регистры этого процессора.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы