Najwięcej mówi o tym temat - jaki jest powód tego, że metody statyczne nie mogą być deklarowane w interfejsie?
public interface ITest {
public static String test();
}
Powyższy kod daje mi następujący błąd (przynajmniej w Eclipse): „Niedozwolony modyfikator dla metody interfejsu ITest.test (); dozwolone są tylko publiczne i abstrakcyjne”.
Odpowiedzi:
Jest tu kilka problemów. Pierwsza to kwestia zadeklarowania metody statycznej bez jej definiowania. To jest różnica między
i
Pierwsza jest niemożliwa z powodów, o których wspomina Espo : nie wiesz, która klasa implementująca jest poprawną definicją.
Java może pozwolić na to drugie; i faktycznie, począwszy od Java 8, tak!
źródło
static
metody w plikuinterface
. Metody muszą byćpublic
.Przyczyna, dla której nie możesz mieć statycznej metody w interfejsie, leży w sposobie, w jaki Java rozwiązuje statyczne odwołania. Java nie będzie zawracać sobie głowy szukaniem instancji klasy podczas próby wykonania metody statycznej. Dzieje się tak, ponieważ metody statyczne nie są zależne od instancji i dlatego mogą być wykonywane bezpośrednio z pliku klasy. Biorąc pod uwagę, że wszystkie metody w interfejsie są abstrakcyjne, maszyna wirtualna musiałaby szukać konkretnej implementacji interfejsu, aby znaleźć kod znajdujący się za metodą statyczną, aby można było ją wykonać. To zaprzecza temu, jak działa statyczna rozdzielczość metody i wprowadziłoby niespójność do języka.
źródło
Odpowiem na twoje pytanie przykładem. Załóżmy, że mamy klasę Math z dodaną metodą statyczną. Nazwałbyś tę metodę w ten sposób:
Gdyby Math był interfejsem zamiast klasą, nie mógłby mieć żadnych zdefiniowanych funkcji. W związku z tym powiedzenie czegoś takiego jak Math.add (2, 3) nie ma sensu.
źródło
Przyczyna leży w zasadzie projektowania, że java nie zezwala na wielokrotne dziedziczenie. Problem z dziedziczeniem wielokrotnym można zilustrować następującym przykładem:
Co się teraz stanie, jeśli wywołasz Cx ()? Czy zostanie wykonane Ax () czy Bx ()? Każdy język z wielokrotnym dziedziczeniem musi rozwiązać ten problem.
Interfejsy pozwalają w Javie na pewne ograniczone dziedziczenie wielokrotne. Aby uniknąć powyższego problemu, nie wolno im używać metod. Jeśli spojrzymy na ten sam problem z interfejsami i metodami statycznymi:
Ten sam problem, co się stanie, jeśli wywołasz Cx ()?
źródło
A
zawierającegoint x(int z);
iB
zawierającego interfejsstring x(int x);
? Jakie jest znaczeniex(3)
w interfejsie C?Metody statyczne nie są metodami instancji. Nie ma kontekstu instancji, dlatego implementacja jej z poziomu interfejsu nie ma sensu.
źródło
Teraz Java8 pozwala nam zdefiniować nawet metody statyczne w interfejsie.
Uwaga: Metody w interfejsie są nadal domyślnie publiczne abstrakcyjne, jeśli nie używamy jawnie słów kluczowych default / static, aby uczynić je metodami domyślnymi i metodami statycznymi.
źródło
Jest to bardzo miłe i zwięzła odpowiedź na swoje pytanie tutaj . (Wydało mi się to przyjemnym, prostym sposobem wyjaśnienia, że chcę go tutaj połączyć.)
źródło
Wygląda na to, że metoda statyczna w interfejsie może być obsługiwana w Javie 8 , cóż, moje rozwiązanie polega po prostu na zdefiniowaniu ich w klasie wewnętrznej.
Tej samej techniki można również użyć w adnotacjach:
Dostęp do klasy wewnętrznej należy zawsze uzyskiwać w postaci
Interface.fn...
zamiastClass.fn...
, wtedy można pozbyć się niejednoznacznego problemu.źródło
Interfejs jest używany do polimorfizmu, który dotyczy obiektów, a nie typów. Dlatego (jak już wspomniano) nie ma sensu mieć statycznego elementu interfejsu.
źródło
Java 8 Zmieniła świat, możesz mieć statyczne metody w interfejsie, ale to zmusza cię do zapewnienia ich implementacji.
}
źródło
Niedozwolone połączenie modyfikatorów: statyczne i abstrakcyjne
Jeśli element członkowski klasy jest zadeklarowany jako statyczny, może być używany z nazwą klasy, która jest ograniczona do tej klasy, bez tworzenia obiektu.
Jeśli element członkowski klasy jest zadeklarowany jako abstrakcyjny, musisz zadeklarować klasę jako abstrakcyjną i musisz zapewnić implementację elementu abstrakcyjnego w jego odziedziczonej klasie (podklasie).
Musisz dostarczyć implementację do abstrakcyjnego elementu klasy w podklasie, w której zamierzasz zmienić zachowanie metody statycznej, również zadeklarowanej jako abstrakcyjna, która jest ograniczona do klasy bazowej, co nie jest poprawne
źródło
Ponieważ metody statyczne nie mogą być dziedziczone. Więc nie ma sensu umieszczać go w interfejsie. Interfejs jest w zasadzie umową, której muszą przestrzegać wszyscy jego abonenci. Umieszczenie statycznej metody w interfejsie zmusi subskrybentów do jej wdrożenia. co teraz staje się sprzeczne z faktem, że metody statyczne nie mogą być dziedziczone.
źródło
Na przykład komparator ma statyczną metodę naturalOrder ().
Zmniejszono również wymaganie, aby interfejsy nie mogły mieć implementacji. Interfejsy mogą teraz deklarować „domyślne” implementacje metod, które są jak zwykłe implementacje z jednym wyjątkiem: jeśli odziedziczysz zarówno domyślną implementację z interfejsu, jak i normalną implementację z nadklasy, implementacja nadklasy zawsze będzie miała priorytet.
źródło
Być może przykładowy kod byłby pomocny, zamierzam użyć C #, ale powinieneś być w stanie to zrobić.
Załóżmy, że mamy interfejs o nazwie IPayable
Teraz mamy dwie konkretne klasy, które implementują ten interfejs:
Teraz udawajmy, że mamy zbiór różnych kont, w tym celu użyjemy ogólnej listy typu IPayable
Teraz chcemy zapłacić 50,00 $ na wszystkie te konta:
Więc teraz widzisz, jak interfejsy są niezwykle przydatne.
Są używane tylko w przypadku obiektów, dla których utworzono instancję. Nie na zajęciach statycznych.
Gdybyś miał ustawioną płatność statyczną, podczas przeglądania IPayable w accountToPay nie byłoby sposobu, aby dowiedzieć się, czy należy wywołać płatność na koncie BusinessAcount czy CustomerAccount.
źródło