• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Java - implementacja pustego interfejsu

0 głosów
456 wizyt
pytanie zadane 16 lutego 2018 w Java przez itcloud Gaduła (3,380 p.)

Może mi ktoś wytłumaczyć "łopatologicznie" o co chodzi z tą serializacją? Tzn. znam ten motyw z php, chociaż robiło się to nieco inaczej i nie miało to związku z żadną obiektowością.

W javie muszę zaimplementować interfejs Serializable. Ten interfejs jest PUSTY. Klasy, które dziedziczą po innych muszę implementować Serializable, klasa rodzic nie musi, chociaż powinna wtedy mieć defaultowy konstruktor, bez parametrów.

ps. wiem, że trzeba implementować, ale gdzie ta cała LOGIKA, silnik serializacji? W ogóle nie czaję, o co chodzi z tymi interfejsami. W przypadku dziedziczenia jest to proste - rozbudowujemy LOGIKĘ. W przypadku interfejsów mamy ew. dowolność dot. wykorzystania własnych IMPLEMENTACJI pewnych metod, można implementować wiele interfejsów, a nie tak jak w przypadku dziedziczenia rozszerzać tylko jedną klasę. Też bym w końcu chciał zrozumieć sens tych interfejsów :( poza rzeczami które można wyczytać w książkach.

komentarz 16 lutego 2018 przez itcloud Gaduła (3,380 p.)
up :)

3 odpowiedzi

+1 głos
odpowiedź 17 lutego 2018 przez mbabane Szeryf (79,260 p.)

Chodzi o to aby Javie dać informacje, że dana klasa może być serializowana np. aby przesłać cały obiekt przez sieć.

Słowo interfejs tutaj ma znaczyć zachowanie. Budowane jest zachowanie obiektów. A na przykład abstract class ma dużo mocniejsze znaczenie dlatego, że prócz zachowania może definiować także różne dodatkowe zależności.

W programowaniu obiektowym chodzi o to aby budować kod na podstawie interfejsów (zachowania), a nie implementacji. Najprostszy przykład to są listy w Javie. Jest tam interfejs List<E> i pisząc taki kod:

ArrayList<String> lista = new ArrayList<>();

jest on całkowicie uzależniony od implementacji ArrayList.  Ale jeśli powyższy kod będzie taki:

List<String> list = new ArrayList<>();

wtedy jest informacja że wystarczy podać tej zmiennej jakąś klasę, która implementuje dany interfejs (w tym przypadku interfejsList<E>). Taki kod jest bardzo elastyczny bo można w dowolnym momencie podmienić new ArrayList<>() np. na new LinkedList<>(), a zachowanie obiektu będzie takie samo.

 

+1 głos
odpowiedź 17 lutego 2018 przez adas94 Nałogowiec (29,260 p.)
edycja 17 lutego 2018 przez adas94
The serialization interface has no methods or fields
* and serves only to identify the semantics of being serializable.

W dużym skrócie nie ma żadnej logiki ani silnika serializacji, ponieważ ten interfejs jest pusty, więc nie ma czego implementować. Logika odpowiadająca za serializację "siedzi" w konkretnych serializatorach. Na przykład, chcesz zserializować swój obiekt do pliku tekstowego. Bierzesz sobie taki ObjectOutputStream i wywołujesz na nim metodę writeObject("twój obiekt"). Ten "twój obiekt" musi mieć interfejs serializable, żeby właśnie ta metoda mogła zadziałać. To jest taki specyficzny rodzaj interfejsu i nie masz się czym przejmować. 

Natomiast jak chcesz zrozumieć "normalne" interfejsy, to @mbabane świetnie wszystko wyjaśnił, jak się wczytasz dobrze, najlepiej kilka razy, to wszystko zrozumiesz.

Jeśli jednak potrzebujesz jeszcze jakiegoś przykładu wykorzystania interfejsów, to na tym forum już o tym pisałem.

https://forum.pasja-informatyki.pl/297721/java-czy-wytlumaczy-ktos-jaka-jest-roznica-miedzy-klasa-abstrakcyjna-interfejsem#a297745

komentarz 17 lutego 2018 przez itcloud Gaduła (3,380 p.)

Ok, tyle w sumie rozumiem, natomiast chyba brakuje mi "obycia" z tym, jak to w praktyce wykorzystać. Piszę teraz o interfejsach. Serializable to tylko przykład który trochę niepotrzebnie mąci. Nadal nie rozumiem, po co, dlaczego, na co takie "dziwne praktyki" z tym serializable. Po to, aby móc skorzystać z metody (logika) writeObject ?

Wracając do praktyki stosowania interfejsów. Poprzez analogię, jak coś piszę w php i chcę np. wczytując nowy plik wiedzieć, czy nie jest to duplikat starego, to w dużym skrócie robię np. tak że wczytuję linia po linii z tego pierwszego pliku do tablicy, a w przypadku drugiego pliku foreachuję tę tablicę i przy każdym wierszu starej tablicy porównuję z wierszem nowej, z tym wierszem który aktualnie "czytam" z tego nowego pliku. Czyli mam sposób, algorytm jak do tego podejść przy zastosowaniu tablicy i foreacha.

Nie bardzo rozumiem, jak zastosować dobrodziejstwo tego interfejsowania. Tzn. tak książkowo patrząc, to wiem że można implementować swoje metody i twórca interfejsu mówi dokładnie jakie. Może jeszcze inaczej, cytując fragment z wątku który poleciłeś:

Poruszanie obiekt;  - i do tego możesz przypisywać wszystkie obiekty klas, które mają zaimplementowany ten interfejs (implementujesz go w Człowiek, Zwierzę, Samochód) ponieważ  te klasy mają w sobie definicję tego interfejsu.

co to znaczy "możesz przypisywać wszystkie obiekty klas", np.

Poruszanie obiekt = ... [tu przypisuje] ? Ale po co, na co ? :)

komentarz 18 lutego 2018 przez adas94 Nałogowiec (29,260 p.)
W takim wypadku polecam wpis na blogu.

http://javastyle.pl/java/polimorfizm-z-wykorzystaniem-interfejsow/

Mam nadzieję, że rozjaśni on nieco sens stosowania interfejsów. :)
komentarz 18 lutego 2018 przez itcloud Gaduła (3,380 p.)

Czyli reasumując, czy sednem mojego pytania o klasę serializable może być taka konkluzja:

Polimorfizm to jedno z największych dobrodziejstw programowania obiektowego. Wyobraźmy sobie, że chcemy rozwinąć nasz program i dodać do niego cztery nowe klasy postaci. W takim wypadku wystarczy tylko zaimplementować interfejs Wojownik w tych klasach i z marszu jesteśmy w stanie dodawać je do drużyny i wyliczać

czyli że jeśli chcę korzystać z serializacji to muszę implementować ten "magiczny" interfejs serializable i nie wnikam ze jest on pusty w środku? Chociaż nadal nie wiem gdzie jest ta logika.

Sam sens polimorfizmu i uzywania interfejsów zrozumiałem w tym kontekście.

1
komentarz 18 lutego 2018 przez adas94 Nałogowiec (29,260 p.)
Pisałeś wcześniej, że masz problem z obyciem z interfejsami, dlatego poleciłem ci ten artykuł. To dotyczy typowych działań na interfejsach. A co do Serializable to tak jak napisałem na samym początku nie ma on implementacji i jest to bardziej kwestia semantyki. To jest dość specyficzny przypadek i najlepiej po prostu przyjąć, że tak ma być. :)
+1 głos
odpowiedź 17 lutego 2018 przez Wiciorny Ekspert (237,450 p.)

Serializacja to wbudowany mechanizm zapisywania obiektów, który pozwala na binarny zapis całego drzewa obiektów. Oznacza to tyle, że jeśli mamy obiekt X, który posiada referencję do obiektu Y to serializując X również Y zostanie automatycznie zapisany w strumieniu wyjściowym.

O czym to mówi: np. mająć pusty interfejs Auto, lub List jak kolega wyżej CI napisał:

tworząc obiekty, takie jak Audi,BMW, Fiat - wszystkie te obiekty są samochodami, z pewnymi różnicami.  Wyobraź sobie, teraz że masz w bazie danych ( table i tak jeden z atrybutów to jest model samochodu )- wybierasz wszystkie zapytaniem modele ... i pakujesz do listy? To widzisz- ta lista zawiera niby, te same, ale jednak całkiem inne obiekty. Bo wszystkie to samochodzy, ale każdy z osobna jest innym samochodem.

Wyobraź sobie teraz sytuacje bez możliwości takiej serializacji z interfejsem Samochodu? Musiałbyś tworzyć liste- dla każdego modelu osobno List<Model1>, List<Model2> i wybierać do nich elementy w warunku np.

A korzystająć jak kolega zwrócił uwagę po prostu z Interfejsu samochód - wszystkie obiekty bedą przekształcone do pewnej postaci 'SERIALIZOWANE' tutaj do Postaci Samochodu, a następnie potem np można na tej zasadzie odwoływać się bezpośrednio do implementacji  

komentarz 17 lutego 2018 przez mbabane Szeryf (79,260 p.)
Nie jestem pewny, czy to co opisujesz to nie zapewnia nam wiązanie dynamiczne, a nie serializacja.
komentarz 17 lutego 2018 przez Wiciorny Ekspert (237,450 p.)
w jednym programie ( waku może ), ale w kwesti przesłania tego poprzez sieć, przesłania do innego programu - całkowicie innego procesu - tylko po to jest serializacja, serializacja w obrębie 1 procesu/1 aplikacji traci sens.

Ale wobec wielkiego projektu wielu procesów/klientów/wątków to jedyna opcja żeby nie spowodować anomalii danych i zachować ich atomowość
komentarz 17 lutego 2018 przez mbabane Szeryf (79,260 p.)

Z tego co zauważyłem, niektórzy programiści terminu serializacja używają też w kontekście, jakby to powiedzieć, "pakowania obiektów gdziekolwiek" w obrębie jednego wątku.

Chciałem zwrócić po prostu uwagę na coś takiego:

interface SomeInterface
{
    void someMethod();
}
class SomeClass implements SomeInterface
{
    @Override
    public void someMethod()
    {
        System.out.println("SomeClass");
    }
}
class OtherClass implements SomeInterface
{
    @Override
    public void someMethod()
    {
        System.out.println("OtherClass");
    }
}
public class Test
{
    public static void main(String[] args)
    {
        List<SomeInterface> list = new ArrayList<>();
        list.add(new SomeClass());
        list.add(new OtherClass());

        for(SomeInterface si : list)
            si.someMethod();
    }
}

Wynik:

SomeClass
OtherClass

Bo według mnie to co opisałeś można, jak wyżej, zapisać w kodzie, czyli jest to klasyczny przykład wiązania dynamicznego, że java sama ogarnia że niby jest interfejs, a gdzieś w głębi jest konkretna klasa. Chodzi mi o to aby utrzymać pewną świadomość i żeby w pewien sposób nie wprowadzać w błąd.

komentarz 17 lutego 2018 przez Wiciorny Ekspert (237,450 p.)
tu nie masz żadnej serializacji stary :D ... to jest po prostu zwykły POLIMORFIZM- dzięki zastosowaniu Interfejsu

 

na liste trafiają 2 obiekty, jeden Obiekt SomeClass Drugi OtherClass i wykonujesz metode interfejsu :) która  jest odpowiednia dla danej instancji na liście czyli wystąpienia.

I masz tu racje sama ogarnia, ale wyobraź sobie- że te rzeczy masz wysłać pomiędzy programami? Zapisanymi w BYTE-CODZIE? Jak druga strona ma wtedy rozumienić o co chodzi, jak dane tutaj są zaimplementowane ? Musisz zapewnić fakt, żeby dane przekazana z TEGO PROCESU do następnego nie uległy modyfikacji. Żeby pewna instancja tutaj- była tą samą instancją w 2 procesie, a nie KOPIĄ CZY NOWĄ
komentarz 17 lutego 2018 przez mbabane Szeryf (79,260 p.)

tu nie masz żadnej serializacji stary :D ... to jest po prostu zwykły POLIMORFIZM- dzięki zastosowaniu Interfejsu 

A czy napisane jest inaczej?

Twoja wypowiedź:

Wyobraź sobie teraz sytuacje bez możliwości takiej serializacji z interfejsem Samochodu? Musiałbyś tworzyć liste- dla każdego modelu osobno List<Model1>, List<Model2> i wybierać do nich elementy w warunku np.

A korzystająć jak kolega zwrócił uwagę po prostu z Interfejsu samochód - wszystkie obiekty bedą przekształcone do pewnej postaci 'SERIALIZOWANE' tutaj do Postaci Samochodu, a następnie potem np można na tej zasadzie odwoływać się bezpośrednio do implementacji  

Czyż nie opisujesz polimorfizmu (wiązania dynamicznego)?

komentarz 17 lutego 2018 przez itcloud Gaduła (3,380 p.)

@Wiciorny,
 trochę ciężko mi się czyta to co napisałeś, bo trochę tak nieskładnie to momentami brzmi. Ale czytając cały wątek chyba domyślam się o co Ci chodziło.

Zmierzasz do tego, że mam różne marki samochodów, różne klasy tych samochodów wg marek, ale każda z tych klas implementuje interfejs Auto, bo każda marka to jest typ auta. I wtedy pewne metody są tak samo nazywane w BMW czy w AUDI ale mogą być nieco inaczej - logicznie - rozpisane, bo ten samochód ma nieco inną specyfikę silnika od drugiego samochodu. Każdy z nich natomiast musi więc zaimplemenotować meotdy typu: jedź(), zatrzymaj_się() itd. Czy to jest ten cały sens interfejsów?

Często widze w zaawansowanym kodzie że argumentem funkcji są właśnie typy interfejsowe. To po to, na takiej samej zasadzie, jak w przypadku poliforizmu i typów generycznych? Że w tablicy można mieć obiekty z "różnych parafii" a nie np. same stringi ?

1
komentarz 17 lutego 2018 przez Wiciorny Ekspert (237,450 p.)
tak dokładnie to jest sens interfejsu, bo każdy z tych obiektów ma też swoje osobne metody np. dzwięk silnika BMW jest inny niz AUDI  ale metoda jedź jest taka sama.

I dokładnie interfejs zapewnia tą elastyczność, że skraca kod, nie musisz się przejmować tym jakie obiekty masz na liście wywołując metode jedź  (), bo interfejs sam odpowiednio dobierze pod typ Obiektu

Podobne pytania

0 głosów
1 odpowiedź 124 wizyt
pytanie zadane 13 sierpnia 2020 w Java przez amtrax Dyskutant (9,560 p.)
0 głosów
3 odpowiedzi 2,645 wizyt
pytanie zadane 20 września 2017 w Java przez Dethavel Początkujący (280 p.)
0 głosów
0 odpowiedzi 690 wizyt
pytanie zadane 28 grudnia 2017 w Java przez bartolinciu Dyskutant (7,620 p.)

89,689 zapytań

138,291 odpowiedzi

309,236 komentarzy

59,620 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...