Dlaczego metody statyczne mogą wykorzystywać tylko dane statyczne?
38
Nie rozumiem, dlaczego metoda statyczna nie może wykorzystywać danych niestatycznych. Czy ktoś może wyjaśnić, jakie są problemy i dlaczego nie możemy tego zrobić?
Ponieważ istnieją tylko dane statyczne z punktu widzenia metod statycznych.
mouviciel
4
Udostępnianie badań pomaga wszystkim. Powiedz nam, co próbowałeś i dlaczego nie spełnia twoich potrzeb. To pokazuje, że poświęciłeś trochę czasu, aby spróbować sobie pomóc, oszczędza nam to powtarzania oczywistych odpowiedzi, a przede wszystkim pomaga uzyskać bardziej konkretną i odpowiednią odpowiedź. Zobacz także How to Ask
gnat
19
@gnat w tym przypadku OP próbuje zrozumieć przyczynę decyzji projektowej. Czego oczekujesz od niego w tej sprawie?
Geek
2
@Geek - istnienie metod statycznych, dane statyczne to problem projektowania języka. Zakładając standardowe znaczenia, fakt, że metody statyczne nie mogą uzyskać dostępu do danych instancji, nie jest. Ograniczenia są implikowane przez definicje i to, co jest możliwe i ma sens, a nie przez niektórych projektantów języków, które są marne.
Steve314,
6
Parafrazując Gertrudę Stein: „Nie ma tam tego ”.
hipopotam-tancerz
Odpowiedzi:
73
W większości języków OO, gdy definiujesz metodę wewnątrz klasy, staje się ona Metodą Instancji . Podczas tworzenia nowego wystąpienia tej klasy za pomocą newsłowa kluczowego inicjujesz nowy zestaw danych unikalny tylko dla tego wystąpienia. Metody należące do tego wystąpienia mogą następnie pracować z danymi na nim zdefiniowanymi.
Natomiast metody statyczne nie znają indywidualnych przypadków klasowych. Metoda statyczna jest podobna do funkcji swobodnej w C lub C ++. Nie jest związany z konkretną instancją klasy. Dlatego nie mogą uzyskać dostępu do wartości instancji. Nie ma instancji, z której można wziąć wartość!
Dane statyczne są podobne do metody statycznej. Zadeklarowana wartość staticnie ma powiązanej instancji. Istnieje dla każdej instancji i jest zadeklarowany tylko w jednym miejscu w pamięci. Jeśli kiedykolwiek ulegnie zmianie, zmieni się dla każdej instancji tej klasy.
Metoda statyczna może uzyskać dostęp do danych statycznych , ponieważ oba istnieją niezależnie od konkretnych instancji klasy.
Pomoże to spojrzeć na to, jak wywołujesz metodę statyczną, w porównaniu do metody instancji. Powiedzmy, że mieliśmy następującą klasę (używając pseudokodu podobnego do Java):
classFoo{// This static value belongs to the class Foopublicstaticfinal string name ="Foo";// This non-static value will be unique for every instanceprivateint value;publicFoo(int value){this.value = value;}publicvoid sayValue(){
println("Instance Value: "+ value);}publicstaticvoid sayName(){
println("Static Value: "+ name);}}Foo foo1 =newFoo(10);Foo foo2 =newFoo(20);
foo1.sayValue();// Prints "Instance Value: 10" - called on foo1
foo2.sayValue();// Prints "Instance Value: 20" - called on foo2Foo.sayName();// Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)
Aktualizacja
Jak POCHODZI punktów w komentarzach, to metoda statyczna jest zdolny do pracy z danymi non-statycznych, ale musi być przekazywane w sposób jawny. Załóżmy, że Fooklasa ma inną metodę:
Addjest wciąż statyczny i nie ma własnych valueinstancji, ale będąc członkiem klasy Foo, może uzyskać dostęp do prywatnych valuepól przekazywanej instancji foo1i foo2instancji. W tym przypadku używamy go, aby zwrócić nowyFoo z dodanymi wartościami obu przekazanych wartości.
Foo foo3 =Foo.Add(foo1, foo2);// creates a new Foo with a value of 30
Rozwijanie „Nie ma instancji, z której można by wziąć wartość” - nawet jeśli istnieją instancje, metoda statyczna nie może wiedzieć, z której instancji należy pobrać wartość.
Steve314,
9
Jest to o wiele mniej skomplikowane do objaśnienia w językach, które nie zmuszają domyślnie wszystkiego do bycia częścią obiektu.
Mason Wheeler,
3
@Mason Prawdziwe słowa. Języki takie jak Java wymuszają fałszywe przekonanie, że funkcja jest czymś, co z konieczności należy do klasy.
KChaloux
5
To dobra odpowiedź, ale wciąż nie mówi całej prawdy: metody statyczne mogą uzyskać dostęp do danych niestatycznych. Po prostu nie mają dostępnego niejawnego obiektu lub thisodwołania. Myślę, że jest to niezwykle ważne, aby zrozumieć.
PRZYJEDŹ Z
2
@COMEFROM Masz na myśli bezpośrednie przekazywanie? Mogę to zanotować, jeśli dobrze cię rozumiem. Zakładałem, że sugerowano, że metoda statyczna może uzyskać dostęp do jawnie przekazanych danych niestatycznych, biorąc pod uwagę, że każda funkcja może działać na danych jawnie do niej przekazanych.
KChaloux
22
Wyjaśnijmy to hipotetyczną próbką.
Wyobraź sobie prostą klasę:
classUser{User(string n){ name = n;};
string name;}
teraz pomyśl - co jeśli dodamy nową metodę statyczną do użytkownika, np .:
static string GetName();
i nazywacie to:
string x =User::GetName()
co by zawierał x? „Jim”, „Bones” czy coś jeszcze?
Problem polega na tym, że metoda statyczna jest pojedynczą metodą zdefiniowaną w klasie, a nie obiektami. W rezultacie nie wiesz, do którego obiektu może się odnosić. Właśnie dlatego jest to wyjątkowa rzecz. Metody statyczne najlepiej traktować jako pojedyncze rzeczy, na przykład funkcje w C. To, że języki takie jak Java zawierają je w klasach, jest głównie problemem z tym, że Java nie pozwala, aby cokolwiek istniało poza klasą, więc takie funkcje muszą być w jakiś sposób wymuszone w klasie (trochę tak, jak musi być main ()) również wewnątrz klasy, kiedy wszystko rozumie, że powinna to być pojedyncza, samodzielna funkcja).
Dane niestatyczne są powiązane z instancją klasy. Metody statyczne (i dane) nie są powiązane z konkretnym wystąpieniem klasy. Nie musi istnieć instancja klasy, aby używać na niej metod statycznych. Nawet gdyby istniały instancje, Java nie byłaby w stanie zagwarantować działania na instancji, której oczekujesz po wywołaniu metody statycznej. Dlatego metody statyczne nie mogą mieć dostępu do danych niestatycznych.
Może korzystać z danych terenowych; rozważ następujący kod java:
classMyBean{privateString myString;staticvoid myStaticMethod(){
myString ="tada";/*not allowed; if this was possible how would
be different from a field without static?*/MyBean myBean =newMyBean();//allowed if associated with an instance
myBean.myString ="tada";}}
Chociaż technicznie może to być metoda statyczna z wykorzystaniem danych niestatycznych, nie ma sensu. Oczywiście możesz utworzyć nową instancję i uzyskać do niej dostęp. Ale to nie ma nic wspólnego z staticnicością.
Bobson,
2
Właściwie uważam, że jest to bardzo dobry dodatek do wyjaśnienia tego. Podkreśla to, że metoda statyczna potrzebuje wystąpienia klasy, zanim będzie mogła uzyskać dostęp do danych niestatycznych, podając jednocześnie intuicyjny powód.
Ben Hocking
@ Bobson Powinieneś również przeczytać kod i komentarze.
m3th0dman
@BenHocking „tak”, nawet myślę, że warto powiedzieć, że „zmienna instancji jest zawsze powiązana z obiektem”
JAVA
2
Myślę, że tutaj chodzi o zrozumienie.
Z technicznego punktu widzenia metoda statyczna wywoływana z obiektu byłaby w stanie zobaczyć pola instancji. Podejrzewam, że właśnie to spowodowało pytanie.
Problem polega na tym, że metody można wywoływać spoza obiektu. W tym momencie nie ma danych instancji do ich dostarczenia - a zatem kompilator nie może rozwiązać kodu. Ponieważ zezwolenie na dane instancji spowodowało sprzeczność, nie możemy pozwolić na dane instancji.
Nie zgadzam się. Metoda statyczna nie może uzyskać dostępu do danych instancji, ponieważ do danych instancji należy uzyskać dostęp za pośrednictwem instancji obiektu, a metoda statyczna nie jest powiązana z żadną instancją (ale z definicją klasy).
Phill W.
Tęsknisz za moim celem. Jeśli zostanie wywołany z klasy, kompilator może przekazać wskaźnik instancji, tak jak robi to, gdy nie jest to klasa statyczna. Problem pojawia się, jeśli jest wywoływany z innego miejsca - co oznacza, że prywatne metody statyczne mogą uzyskiwać dostęp do danych instancji (choć wewnętrznie zasadniczo ignorują dane statyczne).
Loren Pechtel
Tak, kompilator / mógłby / ale dlaczego? Przekazanie takiego wskaźnika zasadniczo redukuje go do metody instancji. Twoje zastrzeżenie, że mogą to robić tylko prywatne metody, jest dyskusyjne - technologie refleksji sprawiają, że / all / metody są dostępne - prywatne lub nie - czyniąc z tego jeszcze bardziej ryzykowną propozycję. Nasi przyjaciele w Redmond poszli w innym kierunku; ich języki generują ostrzeżenie, jeśli próbujesz wywołać metodę statyczną przeciwko instancji obiektu (a nie samej klasie).
Phill W.
1
Pomyśl o tym jak o metodach statycznych żyjących w wymiarze nieorientowanym obiektowo.
W „zorientowanym obiektowo wymiarze” klasa może spawnować wiele ego (instancji), każde ego ma sumienie siebie poprzez swój stan.
W płaskim, nie-OO-wymiarze klasa nie jest świadoma swoich ego żyjących w wymiarze OO. Ich świat jest płaski i proceduralny, prawie tak, jakby OOP nie został jeszcze wynaleziony, i jakby klasa była małym programem proceduralnym, a dane statyczne były tylko zmiennymi globalnymi.
Myślę, że najprostszym sposobem na wyjaśnienie tego jest przyjrzenie się kodowi, a następnie zastanowienie się, jakie wyniki spodziewalibyśmy się, że kod wygeneruje.
// Create three new cars. Cars have a name attribute. Car car1 =newCar("Mazda3");Car car2 =newCar("FordFocus");Car car3 =newCar("HondaFit");// Now we would like to print the names of some cars: // First off why don't we try this: Car.printCarName();// Expected behaviour: // If we think about what we are trying to do here it doesn't// really make sense. What instance of car name should this // print? Should it print Mazda3? FordFoucs?// What is the expected behaviour? If we are going to have a// static call on car call printCarName it should probably do// something like print all car names or a random car name or// throw an error. //Now lets try this instead: Car.printCarName(car1);// Expected Behaviour: // Luckily the expected behaviour is very clear here. This// should print Mazda3. This works as expected. // Finally lets try this:
car1.printMyName();// Expected Behaviour:// Same as previous example, however this is the *right* way// to do it.
Dla kompletności oto klasa samochodów:
publicclassCar{publicString name;publicCar(String name){this.name = name;}publicstatic printCarName(){
print "Not sure what to do here... Don't know which car you are talking about.";}publicstatic printCarName(Car c){
print c.name;}public/*NOT static*/ printMyName(){
print this.name;}}
@gnat Zaktualizowano z komentarzami w celu wyjaśnienia.
sixtyfootersdude
1
Pozostałe odpowiedzi w zasadzie mówią wszystko, jednak jest trochę „szczegółów”, które chciałbym dodać.
Metody statyczne (powiedzmy te w Javie) po prostu nie mają powiązanego z nimi niejawnego obiektu (dostępnego przez this), do którego członków można uzyskać dostęp bezpośrednio bezpośrednio po nazwie.
To nie znaczy, że nie mogą uzyskać dostępu do danych niestatycznych.
classMyClass{publicstaticvoid foo(MyOtherClass object){System.out.println(object.member);}} classMyOtherClass{publicint member =10;}
Wiem, że to tylko szczegół, ale moje pytanie było dziwne, gdy je przeczytałem. „Może używać tylko danych statycznych” jest zbyt restrykcyjne.
Nawiasem mówiąc, nie testowałem kodu, po prostu napisałem go tutaj, aby zilustrować to, co mówiłem.
Odpowiedzi:
W większości języków OO, gdy definiujesz metodę wewnątrz klasy, staje się ona Metodą Instancji . Podczas tworzenia nowego wystąpienia tej klasy za pomocą
new
słowa kluczowego inicjujesz nowy zestaw danych unikalny tylko dla tego wystąpienia. Metody należące do tego wystąpienia mogą następnie pracować z danymi na nim zdefiniowanymi.Natomiast metody statyczne nie znają indywidualnych przypadków klasowych. Metoda statyczna jest podobna do funkcji swobodnej w C lub C ++. Nie jest związany z konkretną instancją klasy. Dlatego nie mogą uzyskać dostępu do wartości instancji. Nie ma instancji, z której można wziąć wartość!
Dane statyczne są podobne do metody statycznej. Zadeklarowana wartość
static
nie ma powiązanej instancji. Istnieje dla każdej instancji i jest zadeklarowany tylko w jednym miejscu w pamięci. Jeśli kiedykolwiek ulegnie zmianie, zmieni się dla każdej instancji tej klasy.Metoda statyczna może uzyskać dostęp do danych statycznych , ponieważ oba istnieją niezależnie od konkretnych instancji klasy.
Pomoże to spojrzeć na to, jak wywołujesz metodę statyczną, w porównaniu do metody instancji. Powiedzmy, że mieliśmy następującą klasę (używając pseudokodu podobnego do Java):
Aktualizacja
Jak POCHODZI punktów w komentarzach, to metoda statyczna jest zdolny do pracy z danymi non-statycznych, ale musi być przekazywane w sposób jawny. Załóżmy, że
Foo
klasa ma inną metodę:Add
jest wciąż statyczny i nie ma własnychvalue
instancji, ale będąc członkiem klasy Foo, może uzyskać dostęp do prywatnychvalue
pól przekazywanej instancjifoo1
ifoo2
instancji. W tym przypadku używamy go, aby zwrócić nowyFoo
z dodanymi wartościami obu przekazanych wartości.źródło
this
odwołania. Myślę, że jest to niezwykle ważne, aby zrozumieć.Wyjaśnijmy to hipotetyczną próbką.
Wyobraź sobie prostą klasę:
Teraz tworzymy 2 wystąpienia tej klasy:
teraz pomyśl - co jeśli dodamy nową metodę statyczną do użytkownika, np .:
i nazywacie to:
co by zawierał x? „Jim”, „Bones” czy coś jeszcze?
Problem polega na tym, że metoda statyczna jest pojedynczą metodą zdefiniowaną w klasie, a nie obiektami. W rezultacie nie wiesz, do którego obiektu może się odnosić. Właśnie dlatego jest to wyjątkowa rzecz. Metody statyczne najlepiej traktować jako pojedyncze rzeczy, na przykład funkcje w C. To, że języki takie jak Java zawierają je w klasach, jest głównie problemem z tym, że Java nie pozwala, aby cokolwiek istniało poza klasą, więc takie funkcje muszą być w jakiś sposób wymuszone w klasie (trochę tak, jak musi być main ()) również wewnątrz klasy, kiedy wszystko rozumie, że powinna to być pojedyncza, samodzielna funkcja).
źródło
Dane niestatyczne są powiązane z instancją klasy. Metody statyczne (i dane) nie są powiązane z konkretnym wystąpieniem klasy. Nie musi istnieć instancja klasy, aby używać na niej metod statycznych. Nawet gdyby istniały instancje, Java nie byłaby w stanie zagwarantować działania na instancji, której oczekujesz po wywołaniu metody statycznej. Dlatego metody statyczne nie mogą mieć dostępu do danych niestatycznych.
źródło
Może korzystać z danych terenowych; rozważ następujący kod java:
źródło
static
nicością.Myślę, że tutaj chodzi o zrozumienie.
Z technicznego punktu widzenia metoda statyczna wywoływana z obiektu byłaby w stanie zobaczyć pola instancji. Podejrzewam, że właśnie to spowodowało pytanie.
Problem polega na tym, że metody można wywoływać spoza obiektu. W tym momencie nie ma danych instancji do ich dostarczenia - a zatem kompilator nie może rozwiązać kodu. Ponieważ zezwolenie na dane instancji spowodowało sprzeczność, nie możemy pozwolić na dane instancji.
źródło
Pomyśl o tym jak o metodach statycznych żyjących w wymiarze nieorientowanym obiektowo.
W „zorientowanym obiektowo wymiarze” klasa może spawnować wiele ego (instancji), każde ego ma sumienie siebie poprzez swój stan.
W płaskim, nie-OO-wymiarze klasa nie jest świadoma swoich ego żyjących w wymiarze OO. Ich świat jest płaski i proceduralny, prawie tak, jakby OOP nie został jeszcze wynaleziony, i jakby klasa była małym programem proceduralnym, a dane statyczne były tylko zmiennymi globalnymi.
źródło
Myślę, że najprostszym sposobem na wyjaśnienie tego jest przyjrzenie się kodowi, a następnie zastanowienie się, jakie wyniki spodziewalibyśmy się, że kod wygeneruje.
Dla kompletności oto klasa samochodów:
źródło
Pozostałe odpowiedzi w zasadzie mówią wszystko, jednak jest trochę „szczegółów”, które chciałbym dodać.
Metody statyczne (powiedzmy te w Javie) po prostu nie mają powiązanego z nimi niejawnego obiektu (dostępnego przez
this
), do którego członków można uzyskać dostęp bezpośrednio bezpośrednio po nazwie.To nie znaczy, że nie mogą uzyskać dostępu do danych niestatycznych.
Wiem, że to tylko szczegół, ale moje pytanie było dziwne, gdy je przeczytałem. „Może używać tylko danych statycznych” jest zbyt restrykcyjne.
Nawiasem mówiąc, nie testowałem kodu, po prostu napisałem go tutaj, aby zilustrować to, co mówiłem.
źródło