Почему прохождение объектов статическими методами было бы выгодно?

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
Это похоже на запах кода, когда два метода делают одно и то же. Если статический метод просто делегировать другому методу, он будет чувствовать себя бесполезным, но не обязательно «плохим»
Nathan Merrill
13
@NathanMerrill Я думаю, вы упускаете суть. Он спрашивает, была ли когда-нибудь ситуация, когда создание и использование второго метода вместо первого было бы предпочтительным.
@Mego Не только методы, приведенные в примере; Я спрашиваю, есть ли какой-нибудь момент, когда использование статических методов и передача объектов лучше, чем вызов методов для объектов?
Эддисон Крамп
Предположительно, вы спрашиваете специально для Java?
enderland
3
Я думаю, что этот вопрос делает молчаливое предположение, что объектно-ориентированный код является своего рода оптимальным. Более процедурный или функциональный подход, естественно, приведет к использованию статических методов. ... Дублировать функциональность между статическим методом и методом экземпляра довольно глупо. Я надеюсь, что это всего лишь пример, и реальный код, о котором вы говорите, имеет только статический характер.
jpmc26

Ответы:

34

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

9000
источник
1
пример: String.Compare в C # (я думаю, что в Java что-то похожее)
edc65
Objects.equals () и Objects.compare () являются примерами в Java, но они не относятся к исходному классу. В стандартной библиотеке Java , по крайней мере, это общепринятая иметь метод экземпляра на что - то вроде объекта, а затем статический метод объекта сек класса.
daboross
20

В вашем примере метод instance - явный победитель.

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

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

  • Вы передаете два или более объектов и хотите подчеркнуть, что они имеют одинаковое значение.

  • null является допустимым значением (как объяснено пользователем 9000).

Heinzi
источник
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();

(оставив корпус "вытянуть" для простоты).

wonderbell
источник
1
Один не передает «весь объект». Вы передаете ссылку на место в памяти, которое представляет собой очень небольшой объем передаваемых данных. Я не уверен в том, какое влияние это оказывает на производительность, но, тем не менее ... также, что подразумевает маркировка "out"?
Эддисон Крамп
1
Я исключил слово «весь» из моего заявления, это сбило с толку. Я никогда не предполагал производительность или размер, ответ основан исключительно на методах программирования. Во всяком случае, outэто .Netключевое слово, используемое в качестве модификатора параметра. В нем говорится, что параметр передается по ссылке. См. Подробности: msdn.microsoft.com/en-us/library/t3c3bfhx.aspx
Wonderbell
4
Первое предложение просто неверно. если у нас есть class C { int x; static void M() { то М вполне может получить доступ x. Например int y = (new C()).x;законно.
Эрик Липперт
@EricLippert :) Я уверен, что вы знаете, что я имел в виду. Удивительно, как мастера могут читать между строк. Может быть, мне нужно отредактировать это предложение. Для пояснения что-то подобное static void M() { this.x = 1; }не возможно.
чудо
1
@wonderbell: Нет, я уверен, что я не знал, что ты имел в виду. Я знал, что ты написал. Я отмечаю, что this.xэто неправильно не потому, xчто к нему нельзя получить доступ, а потому что thisего не существует. Это не вопрос доступа вообще, это вопрос существования .
Эрик Липперт
4

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

Адам Цукерман
источник