Jakie jest uzasadnienie, aby niektóre metody dla typów danych były statyczne?

Aug 15 2020

Na przykład w języku C # istnieją statyczne metody określania, czy ciąg jest pusty, czy też znajdowania elementu w tablicy, czyszczenia tablicy itp. Istnieje jednak metoda wystąpienia zastępująca znaki w ciągu, a zarówno statyczna, jak i instancja metody kopiowania elementów między tablicami.

Podobnie w Pythonie są funkcje do pobierania długości listy, do filtrowania listy itp., Ale przykładowe metody do znajdowania indeksu elementu i kopiowania listy.

Z drugiej strony, w JavaScript prawie każda operacja, którą muszę wykonać na wbudowanym typie danych, będzie dostępna za pośrednictwem metody lub właściwości instancji.

Jakie jest zatem uzasadnienie, aby pewne rzeczy stały się statyczne, a inne nie?

EDYCJA : Żeby było jasne, rozumiem cel metod statycznych. Moje pytanie dotyczy raczej tego, dlaczego niektóre metody są napisane jako statyczne, skoro można je było napisać jako metody instancji. Podobnie jak w Findprzypadku tablic i Formatciągów w C # filteroraz lenw Pythonie.

Odpowiedzi

2 AvnerShahar-Kashtan Aug 15 2020 at 15:09

EDYTUJ : pytanie zostało dopracowane, więc sprecyzuję swoją odpowiedź, ale poprzednie zostawię poniżej, aby komentarze nie były nieistotne.

Może być kilka powodów, dla których warto zaimplementować metodę jako metodę statyczną zamiast metody instancji, przy czym różne języki lub struktury mogą mieć różne uzasadnienia:

  1. Publicznym interfejsem obiektu jest kontrakt. Jeśli twój Arraytyp ujawnia Sortmetodę, każda tablica od teraz, niezależnie od typu lub wersji języka, musi ją obsługiwać. Jeśli jednak an Arrayjest tylko reprezentacją danych w pamięci z cienkim kontraktem, a logika jest przenoszona do klasy takiej jak Array.Sort, zapewnia to większą elastyczność w rozszerzaniu lub modyfikowaniu zachowania bez naruszania zgodności.

  2. Zobacz ten cytat z Clean Code Boba Martina :

Obiekty ujawniają zachowanie i ukrywają dane; Struktura danych ujawnia dane i nie ma znaczącego zachowania ”

W tym przypadku Listklasa jest klasą, która ujawnia zachowanie - ukrywa swoje dane (jest zaimplementowana jako tablica o zmiennym rozmiarze, ale to szczegół implementacji), ale ujawnia funkcjonalność. int[], Choć jest strukturą danych. Jest to intblok przydzielany sekwencyjnie . Ma Lengthwłaściwość, ponieważ jest częścią jego danych , ale nie ma zbyt dużego zachowania - zachowanie jest przenoszone do klasy, która na nim działa.

  1. To może być wybór stylistyczny. Python nie jest wyłącznie językiem obiektowym i może nie mieć gwarancji Java / C # „wszystko jest obiektem”, dlatego zdecydował się na użycie takich funkcji językowych, len()które mogą być używane niezależnie od tego, czy jego parametr jest instancją obiektu, czy nie.

Poprzednia odpowiedź

Uzasadnieniem metod statycznych w C # jest posiadanie metod, które są powiązane z typem, ale nie z wystąpieniem . Może być kilka powodów:

  1. Metody, które mogą działać zarówno na instancji null, jak string.IsNullOrEmptyi oczywiście nie mogą być metodami instancji - ponieważ instancji może nie być.
  2. Podobnie metody fabryczne, które tworzą instancję, nie mają żadnej instancji, z której można by wywołać. Na przykład ktoś przestarzała WebRequest.Create()metoda statyczna zwraca nowe wystąpienie typu pochodzącego z WebRequest.
  3. Chociaż łatwo o tym zapomnieć, .NET ma inną obsługę natywnego typu całkowitego ( int i =5) i otaczającego go typu odwołania w ramce ( object boxed = 5). Jeśli wywołasz metodę typu wartości ( int i = 5; t.ToString();), poniesiesz koszty jej pakowania. Dlatego niektóre operacje nie są zdefiniowane jako metoda na obiekcie, ale jako metoda statyczna, która akceptuje wartość. Dlatego operacje matematyczne, takie jak, Math.Absnie są zdefiniowane jako metody w typach pudełkowych, ale jako funkcje statyczne, które odbierają i zwracają wartości.
  4. Czasami do „konfigurowania” typu używane są metody statyczne, a nie konkretna instancja, ale zachowanie tego typu w systemie. Na przykład [ServicePointManager.SetTcpKeepAlive()][1]konfiguruje zachowanie wszystkich klas, które używają współużytkowanego stosu HTTP (ów) w .NET, dzięki czemu można je wszystkie skonfigurować za pomocą tych statycznych metod.
5 amon Aug 15 2020 at 15:28

Metody statyczne mają dużo sensu

  • gdy metoda jest związana z typem, ale nie wymaga istniejącej instancji; lub
  • kiedy język obsługuje przestrzenie nazw tylko za pośrednictwem klas.

C # obsługuje tylko funkcje jako elementy składowe klas, więc funkcje pomocnicze powinny być zapisywane jako metody statyczne. Klasa C # Mathjest najlepszym przykładem.

JavaScript nie ma klas, ale każda zmienna nielokalna jest powiązana z jakimś obiektem - w przeglądarce większość API jest dostępna przez ten windowobiekt. Istnieją jednak metody, które są dostępne za pośrednictwem obiektu klasowego, np Array.isArray(x).

Python ma specyficzny projekt, który jest w większości zorientowany obiektowo, ale ma kilka wbudowanych funkcji, takich jak len()lub iter(), głównie z powodów historycznych. Pod maską wywołują rzeczywiste metody, np. iter(x)Zwykle x.__iter__(), z rezerwą dla obiektów, które mogą być indeksowane jak lista.

Bardziej interesujące są metody, które staticnie wynikają z dziwactw językowych, ale dlatego, że mają sens. Metody podobne do konstruktorów lub fabryk są klasycznym przykładem, w którym nie mamy istniejącego obiektu, do którego moglibyśmy wywołać metodę. Niektóre funkcje również nie działają na jednym obiekcie, np. String.IsNullOrEmpty(x)Operują na zera lub jednym obiekcie . To nie działa jako metoda, np. x.IsNullOrEmpty()Zgłosi wyjątek, jeśli jest pusty! Array.isArray(x)Sposób w JS jest kolejnym doskonałym przykładem: chcemy zadzwonić isArray(x)na obiektach dowolnego typu, nie tylko na tablicach. W związku z tym metoda instancji nie działa, jeśli nie jest częścią prototypu każdego obiektu.