Зробіть методи, які не залежать від полів екземпляра, статичними?


19

Нещодавно я розпочав програмування в Groovy для рамки тестування інтеграції, для проекту Java. Я використовую Intellij IDEA з плагіном Groovy, і я здивований, коли бачу попередження для всіх методів, які не є статичними і не залежать від будь-яких полів примірника. Однак у Java це не проблема (принаймні, з точки зору IDE).

Чи повинні всі методи, які не залежать від будь-яких полів екземпляра, перетворюватися на статичні функції? Якщо це правда, це специфічно для Groovy чи вона доступна для OOP взагалі? І чому?


Чи називають ці методи іншими методами екземпляра? Або вони буквально не мають нічого спільного з об'єктом цього класу? Чи можете ви навести приклад?
Рей Тол

Відповіді:


26

Зауважте, що IDEA також має цю перевірку для Java, вона називається Метод може бути "статичним" ,

Ця перевірка повідомляє про будь-які методи, які можуть бути безпечно статичними. Метод може бути статичним, якщо він не посилається на будь-який нестатичний метод і нестатичні поля свого класу і не перекривається в підкласі ...

Однак для коду Java ця перевірка вимкнена за замовчуванням (програміст може включити її на власний розсуд). Причиною цього є, швидше за все, те, що обгрунтованість / корисність такої перевірки може бути оскаржена, спираючись на пару досить авторитетних джерел.

Для початку офіційний підручник Java досить обмежує те, коли методи повинні бути статичними:

Загальне використання для статичних методів - це доступ до статичних полів.

Враховуючи вище, можна стверджувати, що включення згаданої перевірки за замовчуванням не відповідає рекомендованому використанню статичного модифікатора на Java.

Крім того, є ще декілька джерел, які пропонують розумний підхід щодо використання ідей, які стоять за цією інспекцією або навіть відштовхують її.

Дивіться, наприклад, статтю Java World - Містер Happy Object вчить статичним методам :

Будь-який метод, який не залежить від стану екземпляра, є кандидатом для того, щоб оголосити статичним.

Зауважте, що я кажу "кандидат за те, що оголошено статичним". Навіть у попередньому прикладі ніщо не змушує вас визнати instances()статичним. Оголошення статичним просто полегшує дзвінки, оскільки для виклику методу вам не потрібен екземпляр. Іноді у вас будуть методи, які, схоже, не покладаються на стан екземпляра. Можливо, ви не хочете робити ці методи статичними. Насправді ви, ймовірно, хочете оголосити їх як статичні, якщо вам потрібно буде отримати доступ до них без примірника.

Більше того, навіть якщо ви можете оголосити такий метод статичним, ви, можливо, цього не захочете через проблеми спадкування, які він втручається у ваш дизайн. Погляньте на "Ефективний об'єктно-орієнтований дизайн", щоб побачити деякі проблеми, з якими ви зіткнетесь ...

Стаття в тестовому блозі Google навіть йде про те, що стверджують, що статичні методи - це смерть для заповіту :

Давайте робити розумові вправи. Припустимо, ваша програма не має нічого, крім статичних методів. (Так, такий код можна записати, він називається процедурним програмуванням.) Тепер уявіть графік виклику цієї програми. Якщо ви спробуєте виконати метод аркуша, у вас не виникне проблем із встановленням його стану та затвердженням усіх кутових справ. Причина полягає в тому, що листковий метод більше не вимагає. Коли ви віддаляєтесь далі від листя і ближче до кореневого main()методу, то важче і важче буде встановити стан у вашому тесті і складніше стверджувати речі. Багато речей стане неможливим стверджувати. Ваші тести будуть прогресивно збільшуватися. Як тільки ви досягнетеmain()методу, у вас більше немає одиничного тесту (оскільки ваша одиниця є всією програмою), тепер у вас є тест сценарію. Уявіть, що програма, яку ви намагаєтеся протестувати, - це текстовий процесор. Ви не можете стверджувати з основного методу ...

Іноді статичні методи - це завод для інших об’єктів. Це ще більше обтяжує проблему тестування. У тестах ми розраховуємо на те, що ми можемо об'єднати об'єкти по-різному, замінюючи важливі залежності макетами. Після виклику newоператора ми не можемо замінити метод з підкласом. Абонент такого статичного заводу постійно пов'язаний з класами бетону, які виробляв статичний заводський метод. Іншими словами, пошкодження статичного методу значно перевищує сам статичний метод. Бутінг об'єднання графіків об'єктів та код побудови в статичний метод є надзвичайно поганим, оскільки проводка графіка об'єкта - це те, як ми ізолюємо речі для тестування ...


Розумієте, згадане вище виглядає лише природно, що згаданий огляд вимкнено для Java за замовчуванням.

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

Для Groovy все зовсім інакше. Жоден із перелічених вище аргументів не застосовується, особливо той, що стосується доказів, як це було пояснено, наприклад, у глузливих статичних методах у статті Groovy в Javalobby:

Якщо клас Groovy, який ви тестуєте, викликає статичний метод для іншого класу Groovy, тоді ви можете використовувати ExpandoMetaClass, який дозволяє динамічно додавати методи, конструктори, властивості та статичні методи ...

Ця різниця, ймовірно, чому налаштування за замовчуванням для згаданої інспекції є протилежним у Groovy. Якщо в Java за замовчуванням "увімкнено" буде джерело плутанини користувачів, в Groovy протилежна настройка може заплутати користувачів IDE.

"Гей метод не використовує поля екземплярів, чому ви не попередили мене про це?" На це питання було б легко відповісти для Java (як було пояснено вище), але для Groovy просто не існує переконливого пояснення.


До речі, ReSharper (зроблений JetBrains для C # / Visual Studio) пропонує те саме
Конрад Моравський

6
Існує важлива відмінність статичних методів із побічними ефектами та без них. Екстракт Google дійсно стосується колишнього.
assylias

@assylias Це так, але він також обговорює, як заводські методи можуть зробити складніше тестування (оскільки він щільно з'єднує залежності в додатку). Використання системи введення залежності є одним з найкращих способів вирішення цього питання, а також вирішує багато інших проблем.
Пер Лундберг

5

Важко уявити, що це вплине на продуктивність. Єдина перевага, яку я бачу, щоб зробити їх, staticце те, що вона забезпечує візуальну вказівку на те, що стан екземпляра не впливає. Іншими словами, він повідомляє людині, яка читає вихідний код щось ... "цікаве" про цей метод, саме завдяки тому, що він там присутній. Справжнє запитання полягає в тому, чи це уточнює чи плутає? "Чому цей метод статичний? Це заводський метод? Чи потрібна можливість викликати його без примірника об'єкта?"

Крім того, деяким людям не подобаються статичні методи, оскільки вони стверджують, що з них не можна знущатися, і тому вони не перевіряються, або щось подібне. Звичайно, якщо ви робите це статичним з будь-яких звичних причин, наприклад, наприклад, із забезпеченням фабричного методу, я все для цього. Я просто не зовсім впевнений, що зробити методи статичними лише тому, що вони не торкаються стану екземпляра - це мандат.


5
Вважайте, що (в межах Java) статичний метод не можна перекрити. Хоча це не часто проблема, це означає, що деякий підклас пізніше не може змінити цю реалізацію. Це не означає, що статичний метод не є правильною відповіддю, а є частиною міркувань щодо дизайну.

2
@ user40980 це варто врахувати, правда, але також варто врахувати, що успадкування може бути незграбним інструментом, який часто зловживають, і кілька видатних діячів стверджують, що всі класи повинні бути finalабо спеціально розроблені з урахуванням спадкування.
сара

3

Я думаю , що це для того, щоб можливий рефакторінга бути помічений .

Після того, як метод став статичним, зрозуміло, що його можна перемістити з класу, скажімо, до класу єдності.

Також легко перетворити його в метод екземпляра одного з його параметрів, часто саме тут має бути код.


-1

Зауважте, що у вас можуть бути класи без громадянства, які реалізують деякий інтерфейс (наприклад, java.lang.Runnableви не можете зробити їх методи статичними. Деякі зразки (наприклад, стратегія) також можуть створювати об'єкти без громадянства, які можуть мати навіть кілька методів.

Статики - це перші родички синглів. Перейти від статики до нестатики буде пізніше дуже важко - тому, коли вам потрібно буде додати стан, ви будете спокушені почати вводити статичні змінні.


як це відповідає на поставлене запитання?
гнат

1
чому важко переходити з жодної держави до якоїсь держави? Я б сказав, що це навпаки. простіше забруднити щось чисте, ніж очистити щось забруднене.
сара
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.