Dlaczego przekazywanie obiektów metodami statycznymi byłoby korzystne?

9

Dlaczego miałaby być korzyść ze stosowania metody statycznej i przekazywania odwołania do obiektu jako parametru zamiast wywoływania metody na obiekcie?

Aby wyjaśnić, co mam na myśli, rozważ następującą klasę:

public class SomeClass {
    private double someValue;

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

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

W porównaniu z tą alternatywną implementacją metodą statyczną:

public class SomeClass {
    private double someValue;

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

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

Moje pytanie nie ogranicza się tylko do tej klasy; interesuje mnie każdy punkt, w którym można przekazać obiekt zamiast wywoływać go za pomocą metody. Czy jest to kiedykolwiek korzystne? Jeśli tak, to dlaczego?

Addison Crump
źródło
1
Czuje się jak zapach kodu z dwiema metodami wykonującymi dokładnie to samo. Gdyby metoda statyczna została po prostu delegowana na inną metodę, czułaby się bezużyteczna, ale niekoniecznie „zła”
Nathan Merrill,
13
@NathanMerrill Myślę, że brakuje ci sensu. Pyta, czy kiedykolwiek zdarzy się sytuacja, w której lepiej byłoby utworzyć i zastosować drugą metodę zamiast pierwszej.
@Mego Nie tylko metody podane w przykładzie; Pytam, czy jest jakiś moment, kiedy używanie metod statycznych i przekazywanie obiektów jest lepsze niż wywoływanie metod na obiektach?
Addison Crump,
Prawdopodobnie pytasz konkretnie o Javę?
Enderland
3
Myślę, że to pytanie zakłada milcząco, że obiektowy kod jest pewnym rodzajem optymalnego. Podejście bardziej proceduralne lub funkcjonalne naturalnie doprowadziłoby do zastosowania metod statycznych. ... Powielanie funkcjonalności między metodą statyczną a instancją jest jednak dość głupie. Mam nadzieję, że to tylko przykład, a faktyczny kod, o którym mówisz, ma tylko wartość statyczną.
jpmc26

Odpowiedzi:

34

Trywialny przykład: kiedy przekazana instancja może być zerowa i chcesz włączyć (nietrywialną) obsługę tej metody do metody.

9000
źródło
1
przykład: String.Compare in C # (myślę, że jest coś podobnego w Javie)
edc65
Objects.equals () i Objects.compare () są przykładami w Javie - ale nie należą do oryginalnej klasy. W standardowej biblioteki Java przynajmniej, to wspólny mieć metodę instancji na coś podobnego obiektu, ale wtedy metody statycznej na obiekt s klasy.
daboross
20

W twoim przykładzie metoda instancji jest wyraźnym zwycięzcą.

W ogólnym przypadku mogę wymyślić kilka powodów, dla których statyczna metoda może być odpowiednia:

  • Chcesz umieścić metodę statyczną w innej klasie, ponieważ masz sytuację, w której sensowne jest oddzielenie logiki od danych (uwaga: twój przykład nie jest jedną z nich).

  • Mijasz dwa lub więcej obiektów i chcesz podkreślić, że mają one jednakowe znaczenie.

  • null jest prawidłową wartością (zgodnie z wyjaśnieniem użytkownika 9000).

Heinzi
źródło
5

Mądrze byłoby uwzględnić metody zmieniające stan obiektu jako metody instancji zamiast metody statycznej .

Możemy jednak znaleźć przykłady metod statycznych, które są puremetodami, i przyjąć obiekt jako dane wejściowe, na przykład gdy musimy utworzyć instancję obiektu na podstawie pewnych reguł sprawdzania poprawności. Na przykład .NET ma metodę DateTime.TryParse(String s, DateTime d)sprawdzania poprawności i tworzenia instancji obiektu. Ale parametr DateTime djest wyraźnie oznaczony jako out.

Kolejny przypadek może mieć miejsce, gdy porównujemy obiekty i chcemy uzyskać pożądany obiekt jako wartość zwracaną, a nie na przykład wartość logiczną / całkowitą wyniku porównania Team.GetHigherScorer(teamA, teamB).IncreaseRanking(). Będzie to czystsze niż:

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

(pozostawiając przypadek „wyciągnąć” dla uproszczenia).

cudowny dzwonek
źródło
1
Nie przekazuje się „całego obiektu”. Przekazujesz odwołanie do miejsca w pamięci, które jest przekazywane bardzo niewielkiej ilości danych. Nie jestem pewien, jaki to ma wpływ na wydajność, ale mimo wszystko ... co oznacza oznaczenie „out”?
Addison Crump
1
Usunąłem słowo „całe” z mojego oświadczenia, było mylące. Nigdy nie zamierzałem wydajności ani rozmiaru, odpowiedź opiera się wyłącznie na praktykach programistycznych. W każdym razie outjest .Netsłowem kluczowym używanym jako modyfikator parametru. Wskazuje, że parametr jest przekazywany przez odwołanie. Zobacz szczegóły msdn.microsoft.com/en-us/library/t3c3bfhx.aspx
wonderbell
4
Pierwsze zdanie jest po prostu złe. jeśli tak, class C { int x; static void M() { to M ma doskonały dostęp x. Na przykład int y = (new C()).x;jest legalny.
Eric Lippert,
@EricLippert :) Jestem pewien, że wiesz, co miałem na myśli. To niesamowite, jak mistrzowie potrafią czytać między wierszami. Być może muszę edytować to zdanie. Dla wyjaśnienia, coś takiego static void M() { this.x = 1; }nie jest możliwe.
wonderbell
1
@wonderbell: Nie, jestem pewien, że nie wiedziałem, co masz na myśli. Wiedziałem co napisałeś. Zauważam, że this.xjest to złe nie dlatego, że xnie można uzyskać do niego dostępu, ale dlatego, thisże nie istnieje. To wcale nie jest kwestia dostępu , to kwestia istnienia .
Eric Lippert,
4

Zastrzyk zależny byłby dobrym powodem do wywołania metody statycznej. Zakładając, że konkretna implementacja SomeClassma łańcuch dziedziczenia lub jest implementacją innej klasy. Możesz użyć makiety obiektu, przekazać go do celów testowych, aby upewnić się, że twoja metoda robi to, co powinna, a następnie zgłosić ten status.

Adam Zuckerman
źródło