Чому передача об'єктів статичними методами буде вигідною?


9

Чому було б перевагою використовувати статичний метод і передавати посилання на об’єкт як параметр, а не викликати метод на об'єкт?

Щоб уточнити, що я маю на увазі, розглянемо наступний клас:

public class SomeClass {
    private double someValue;

    public SomeClass() {
        // Some constructor in which someValue is set
    }

    public void incrementValue() {
        someValue++;
    }
}

Порівняно з цією альтернативною реалізацією статичним методом:

public class SomeClass {
    private double someValue;

    public SomeClass() {
        // Some constructor in which someValue is set
    }

    public static void incrementValue(SomeClass obj) {
        obj.someValue++;
    }
}

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


1
Це відчуває, як кодовий запах двома методами, які роблять точно те саме. Якщо статичний метод просто делегували іншому методу, то він почувався б марним, але не обов'язково "поганим"
Натан Меррілл

13
@NathanMerrill Я думаю, що ви пропускаєте суть. Він запитує, чи не виникає ситуація, коли створення та використання другого методу замість першого методу було б кращим.

@Mego Не тільки методи, наведені в прикладі; Я запитую, чи є якийсь момент, коли використовувати статичні методи та передавати об’єкти краще, ніж викликати методи на об’єкти?
Аддісон Кримп

Імовірно, ви просите спеціально для Java?
Ендерленд

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

Відповіді:


34

Тривіальний приклад: коли переданий екземпляр законно може бути нульовим, і ви хочете включити (нетривіальне) обробку цього методу в метод.


1
приклад: String.Compare в C # (я думаю, що в Java є щось подібне)
edc65

Object.equals () та Objects.compare () - приклади Java, але вони не є в початковому класі. Принаймні, у стандартній бібліотеці Java звичайний метод екземпляра є на зразок Object, але потім статичний метод у класі Object s .
даборосс

20

У вашому прикладі метод екземпляра є явним переможцем.

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

  • Ви хочете поставити статичний метод в інший клас, оскільки у вас є ситуація, коли є сенс відокремити логіку від даних (зверніть увагу: ваш приклад не є одним із них).

  • Ви проходите два або більше об'єктів і хочете підкреслити, що вони мають однакове значення.

  • null є дійсним значенням (як пояснив користувач 9000).


5

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

Однак ми можемо знайти приклади статичних методів, які є pureметодами, і приймають об’єкт як вхід, як, коли нам потрібно інстанціювати об'єкт на основі певних правил перевірки. Наприклад, .NET має метод DateTime.TryParse(String s, DateTime d)перевірки та інстанціювання об'єкта. Але параметр DateTime dявно позначений як out.

Інший випадок може бути, коли ми порівнюємо об'єкти і хочемо отримати потрібний об'єкт як повернене значення, а не булеве / ціле значення, наприклад, порівняння Team.GetHigherScorer(teamA, teamB).IncreaseRanking(). Це буде чистіше, ніж:

int compareResult = teamA.compareScoreWith(teamB);
if (compareResult == 1)
    teamA.IncreaseRanking();
else if (compareResult == -1) 
    teamB.IncreaseRanking();

(залишаючи випадок «намалювати» для простоти).


1
Один не передає "цілого об'єкта". Ви передаєте посилання на місце в пам'яті, яке передається дуже малою кількістю даних. Я не впевнений у впливі на продуктивність, який це має, але, тим не менше ... також, що означає маркування "поза"?
Аддісон Кримп

1
Я кинув слово "цілий" зі своєї заяви, це було заплутано. Я ніколи не задумував продуктивність чи розмір, відповідь суто базується на практиці програмування. У будь-якому випадку outце .Netключове слово, яке використовується як модифікатор параметрів. У ньому зазначено, що параметр передається посиланням. Детальніше див. Msdn.microsoft.com/en-us/library/t3c3bfhx.aspx
wonderbell

4
Перше речення просто неправильне. якщо ми маємо, class C { int x; static void M() { то M цілком може отримати доступ x. Наприклад int y = (new C()).x;, законний.
Ерік Ліпперт

@EricLippert :) Я впевнений, що ти знаєш, що я мав на увазі. Дивно, як майстри можуть читати між рядків. Можливо, мені потрібно відредагувати це речення. Для уточнення щось подібне static void M() { this.x = 1; }неможливо.
чудеса

1
@wonderbell: Ні, я впевнений, що я не знав, що ти маєш на увазі. Я знав, що ти написав. Зауважу, що this.xце неправильно не тому, що xне можна отримати доступ, а тому, thisщо не існує. Це взагалі не питання доступу , це питання існування .
Ерік Ліпперт

4

Ін'єкція залежності буде вагомою причиною для здійснення виклику статичного методу. Якщо припустити, що конкретна реалізація системи SomeClassмає спадковий ланцюг або це реалізація іншого класу. Ви можете використовувати макет об'єкта, передавати його для тестування, щоб переконатися, що ваш метод робить те, що належить, а потім звітувати про цей стан.

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