Sens używania interfejsów

Sens używania interfejsów
M4
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:11
0
Shakaz napisał(a):

Why interface is useful
Jak dla mnie najlepsze wytłumaczenie interfejsu.

@marcin43210 Przeczytaj i powiedz, własnymi słowami, jak to rozumiesz.

Rozumiem to w taki sposób, że interfejs ułatwia pracę, pomaga, z nim jest dużo prościej i sprawniej, ale bez niego też się da coś zrobić (kosztem większego skomplikowania np).

grzesiek51114
grzesiek51114
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 4 lata
  • Postów:2442
0

...ale bez niego też się da coś zrobić (kosztem większego skomplikowania np).

Nawet nieobiektowo się da. Pytanie tylko po co?

@Shakazowi chodziło o to żebyś opisał własnymi słowami co to jest i jak działa interfejs.

edytowany 1x, ostatnio: grzesiek51114
Shakaz
  • Rejestracja:ponad 10 lat
  • Ostatnio:10 miesięcy
  • Postów:184
0

@marcin43210 Czy Ty w ogóle przeczytałeś to, co Ci zalinkowałem?

ułatwia pracę, pomaga, z nim jest dużo prościej i sprawniej - taką definicję mogę podać do większości wykorzystywanych mechanizmów...

edytowany 3x, ostatnio: Shakaz
Zobacz pozostały 1 komentarz
M4
No rozumiem to w ten sposób, że mając 2 obiekty, które robią coś podobnego (w tym przypadku wkurzają gości), robią to w inny sposób. Interfejs pozwala na zdefiniowanie funkcji w ten sposób, że dla różnych obiektów będzie działać ona inaczej, ale w rezultacie robi to samo. Czyli np. samochód jest napędzany i rower też jest napędzany, ale samochód w inny sposób (spalanie paliwa przez silnik) i rower też w inny sposób (siła rowerzysty) a w rezultacie oba obiekty zwiększają prędkość.
caer
@marcin43210 no to rozumiesz kiedy się stosuje interfejsy, ale rozumiesz po co?
M4
wg mnie po to, żeby np. nie wywoływać danej metody na każdym obiekcie, tylko mieć możliwość wywołania tej metody za pomocą pętli, która przechodzi po różnych obiektach. To tak jakbym podobne działaniem obiekty sprowadził do typu, który umożliwi ich takie samo działanie, ale każdy w inny sposób. Bez interfejsu musiałbym robić takie działania na każdym obiekcie osobno, czyli wychodzi wtedy masa kodu do napisania, a z interfejsem przechodzę po obiektach implementujących ten iterfejs, co pozwala na nich działać. Nie wiem, czy zrozumiale to opisałem, ale staralem się...
Jaca777
@marcin43210 Tak, o to w tym przykładzie chodzi. Ale to można rozszerzyć, np. interfejs Repository pozwalający na zapis i odczyt danych. Nie wiesz gdzie ona je zapisuje, może w bazie danych, w pliku, w liście. Nie interesuje Cię to. Jedyne co robisz, to przyjmujesz to jako argument metody czy konstruktora. I zobacz jak w takiej sytuacji łatwo zmienić sposób zapisu - zamiast klasy zapisującej w bazie danych podrzucasz klasę zapisującą w liście i nigdzie nie musisz edytować kodu.
Shakaz
Rzeczy związane z tematem zawierajcie w postach, nie w komentarzach. Jest tu sporo informacji nt. omawianego zagadnienia, co może komuś umknąć.
Shakaz
  • Rejestracja:ponad 10 lat
  • Ostatnio:10 miesięcy
  • Postów:184
0

Super, rozumiesz już istotę interfejsów. Teraz, wykorzystując dziedziczenie oraz polimorfizm, masz kolekcję obiektów NapędzanyPojazd. Teraz w tej kolekcji możesz przechowywać rower, samochód, samolot, helikopter - bo przecież każdy z nich jest napędzany, prawda? Na tym przykładzie powiedz mi, jak w kodzie, za pomocą jakiegoś guzika START, wywołasz, aby każdy z 4 w.w. obiektów zaczął się poruszać? (pseudokod wystarczy)

edytowany 4x, ostatnio: Shakaz
M4
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:11
0
Shakaz napisał(a):

Super, rozumiesz już istotę interfejsów. Teraz, wykorzystując dziedziczenie oraz polimorfizm, masz kolekcję obiektów NapędzanyPojazd. Teraz w tej kolekcji możesz przechowywać rower, samochód, samolot, helikopter - bo przecież każdy z nich jest napędzany prawda? Na tym przykładzie powiedz mi, jak w kodzie, za pomocą jakiegoś guzika START, wywołasz, aby każdy z 4 w.w. obiektów zaczął się poruszać? (pseudokod wystarczy)

Więc tak:
Tworzę interfejs, np.:

Kopiuj
public interface Start {
          void goFaster();
} 

Potem tworzę każdą z klas (samlot, samochód itd....), w której jest prędkość. Czyli np:

Kopiuj
 
public class Car implements Start
{
int speed=0;
	void goFaster()
	{
		speed+=10;
	}
}

I tak każdą klasę, ale oczywiście w każdej z nich kod metody goFaster będzie inny.

Później tworzę ArrayList List<Start> napedzanyPojazd = new ArrayList<>(); i ją wypełniam tymi obiektami. I w tym momencię mogę po tej liście przejść wywołując na każdym elemencie metodę "goFaster". Czyli nie muszę się po kolei odwoływać do każdego obiektu.

edytowany 2x, ostatnio: marcin43210
Zobacz pozostały 1 komentarz
M4
Tak, tak, przepraszam... pomyliłem się, ale chodziło mi o goFaster. Już poprawiłem
Shakaz
ps. Lepszą nazwą dla tego interfejsu byłoby Startable
M4
No tak, każdy interfejs powinien mieć 'able', a przynajmniej wypadałoby żeby miał. Tak wyczytałem poza tym wszystkie wbudowane interfejsy javy mają 'able' z tego co zdążyłem się douczyć :)
M4
ooo, dzięki, przyda się:)
Shakaz
  • Rejestracja:ponad 10 lat
  • Ostatnio:10 miesięcy
  • Postów:184
0

@marcin43210 Brawo! Proste, nieprawdaż? :)

Interfejsy też pozwalają na zastosowanie abstrakcji w taki sposób, jak to opisał @Jaca777 w komentarzu wyżej. Masz pomysł, o co konkretnie może chodzić?

M4
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:11
0
Shakaz napisał(a):

@marcin43210 Brawo! Proste, nieprawdaż? :)

Interfejsy też pozwalają na zastosowanie abstrakcji w taki sposób, jak to opisał @Jaca777 w komentarzu wyżej. Masz pomysł, o co konkretnie może chodzić?

No wlaśnie proste... ale najelpiej na takich właśnie przykłądach to zrozumieć. Wszędzie jest ogólny sens interfejsów, a przykładów, które w łopatologiczny sposób by pomogły je zrozumieć już tak dużo nie ma. Myślę, że wielu osobom ten temat pomoże:)
Co do postu kolegi jaca, to tak średnio rozumiem, co ma na myśli bo stwierdzenie typu "dodajesz to do konstruktora" nie mówi mi dużo. Co dodaje do konstruktora? Może jakiś przykład? Na pewno by mi wyjaśnił o co mu dokładnie chodzi:)

Shakaz
  • Rejestracja:ponad 10 lat
  • Ostatnio:10 miesięcy
  • Postów:184
0
marcin43210 napisał(a):

No wlaśnie proste... ale najelpiej na takich właśnie przykłądach to zrozumieć. Wszędzie jest ogólny sens interfejsów, a przykładów, które w łopatologiczny sposób by pomogły je zrozumieć już tak dużo nie ma. Myślę, że wielu osobom ten temat pomoże:)

Nigdy w pełni nie zrozumiesz czegoś, dopóki nie przekonasz się na własnej skórze - czyli tworząc/modyfikując/czytając kod(tak, z czytania/przeglądania kodu idzie sporo się nauczyć).

Co do postu kolegi jaca, to tak średnio rozumiem, co ma na myśli bo stwierdzenie typu "dodajesz to do konstruktora" nie mówi mi dużo. Co dodaje do konstruktora? Może jakiś przykład? Na pewno by mi wyjaśnił o co mu dokładnie chodzi:)

Co może być argumentem w metodzie/konstruktorze?

caer
mimo wszystko wstrzykiwanie zależności to już trochę bardziej zaawansowany temat
Shakaz
Być może. Najwyżej wróci sobie w przyszłości do tego ;)
M4
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:11
0
Shakaz napisał(a):
marcin43210 napisał(a):

No wlaśnie proste... ale najelpiej na takich właśnie przykłądach to zrozumieć. Wszędzie jest ogólny sens interfejsów, a przykładów, które w łopatologiczny sposób by pomogły je zrozumieć już tak dużo nie ma. Myślę, że wielu osobom ten temat pomoże:)

Nigdy w pełni nie zrozumiesz czegoś, dopóki nie przekonasz się na własnej skórze - czyli tworząc/modyfikując/czytając kod(tak, z czytania/przeglądania kodu idzie sporo się nauczyć).

Co do postu kolegi jaca, to tak średnio rozumiem, co ma na myśli bo stwierdzenie typu "dodajesz to do konstruktora" nie mówi mi dużo. Co dodaje do konstruktora? Może jakiś przykład? Na pewno by mi wyjaśnił o co mu dokładnie chodzi:)

Co może być argumentem w metodzie/konstruktorze?

Co może być? No w zasadzie to wszytko. Każdy obiekt.

Shakaz
  • Rejestracja:ponad 10 lat
  • Ostatnio:10 miesięcy
  • Postów:184
0

np. interfejs Repository pozwalający na zapis i odczyt danych + Jedyne co robisz, to przyjmujesz to jako argument metody czy konstruktora.

To na podstawie tego, stwórz sygnaturę metody save oraz read.

edytowany 2x, ostatnio: Shakaz
caer
  • Rejestracja:około 11 lat
  • Ostatnio:11 miesięcy
  • Postów:465
0

No właśnie, a ty nie chcesz każdego obiektu, chcesz tylko takie które mogą zrobić to co chcesz, czyli zapisywać dane do bazy/pliku.

M4
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:11
0

Póki co to odpuszczam. Ważne, że ogarnałem sens i zastosowanie podstawowe interfejsów. To o czym teraz piszecie, to dla mnie czarna magia, nie wiem w ogole o co chodzi, dlatego na spokojnie powoli do tego dojdę za jakiś czas pewnie. Podaje interfejs jako argument i co dalej? Jak to ma się do tych zależności? Dla mnie jest ciężko zakumać cokolwiek bez przykładu. Sama teoria nic mi nie daje, muszę mieć coś pokazane w uzyciu. To tak jak z jazdą samochodem - wiesz, że musisz wbić bieg, puscic sprzęgło i dać gaz i wiesz za co każdy pedał odpowiada, ale musisz jednakl zobaczyć w praktyce jak to wygląa żeby zrozumieć i zacząć to stosować:)

edytowany 1x, ostatnio: marcin43210
Jaca777
  • Rejestracja:ponad 9 lat
  • Ostatnio:11 miesięcy
2

W takim razie:

Kopiuj
 
    interface Repository {
        void save(User user);
        User get(String userName);
    }
    
    class FileRepository implements Repository {

        @Override
        public void save(User user) {
            //Zapisywanie w pliku
        }

        @Override
        public User get(String userName) {
            //Odczyt z pliku i zwracanie
        }
    }
    
    class MySQLRepository implements Repository {

        @Override
        public void save(User user) {
            //zapis do bazy danych
        }

        @Override
        public User get(String userName) {
            // odczyt z bazy danych i zwracanie
        }
    }
    
    class UserInterface {
        private Repository repository;

        public UserInterface(Repository repository) {
            this.repository = repository;
        }
        
        public void showUser(String userName) {
            User user = repository.get(userName);
            //Wyświetlanie za pomocą dialogu
        }
        
        public String readAndSaveUser() {
            User user = //Pokazanie dialogu i wczytanie danych
            repository.save(user);
            return user.getName();
        }
    }
    
    public static void main(String... args) {
        Repository repository = new FileRepository();
        UserInterface userInterface = new UserInterface(repository);
        String userName = userInterface.readAndSaveUser();
        userInterface.showUser(userName);
    }

Przeanalizuj ten kod i pomyśl co zmienić w nim, aby zapisywał użytkowników w bazie danych.

edytowany 2x, ostatnio: Jaca777
Zobacz pozostały 1 komentarz
Jaca777
Dokładnie o to chodzi. Czy to nie jest cholernie wygodne?
M4
No jest:) Dopiero po przykładzie zakumałem. Super sprawa! Serdeczne dzięki :)
Jaca777
I właśnie to przekazywanie Repository nazywa się wstrzykiwaniem zależności (DI), a dokładniej odwróceniem sterowania (IoC). I nie musisz robić tego przez konstruktor - jakiś setter czy nawet refleksja dadzą ten sam efekt.
AO
@Jaca777 refleksja, to znaczy (w javie) oczekiwanie typu Class, podania tego czegoś przez nazwę klasy + .class/.getClass() i te metody do zapisu/odczytu statyczne?
Jaca777
@AvgObject Nie, to znaczy ustalenie w pliku konfiguracyjnym lub przez adnotacje nazw pół, do których ma zostać wstrzyknięty jakiś obiekt. Następnie moduł odpowiedzialny za wstrzykiwanie zależności zmieni ich wartość za pomocą refleksji przy tworzeniu obiektu. Tak działa np. wstrzykiwanie zależności w Springu.
M4
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:11
0

Ok, wieczorkiem sobie przeanalizuję krok po kroku :) Dzięki wszystkim za cierpliwość i pomoc bo dzięki Wam zacząłem to wreszcie trochę kumać:)

Gjorni
  • Rejestracja:około 12 lat
  • Ostatnio:około 3 lata
2

PS @Shalom @bogdans i inni moderatorzy - co Wy na to, aby w jakiś magiczny moderatorski sposób podpiąć, gdzieś ten temat, albo uwzględnić go w jakimś forumowym, javowym kompedium? Bądź, co bądź, całkiem nieźle zostały tutaj opisane interfejsy dla początkującego.


The quieter you become, the more you are able to hear.
azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
0

@marcin43210 nie czytałem całego wątku i nie wiem czy to zostało poruszone ale interfejs można fajnie wytłumaczyć na przykładzie filter pattern
nie mam czasu pisać example, ale ogólnie chodzi o to że masz np interfejs Filter z metodą filter() i robisz np 3 implementacje: StartsWithUppercaseFilter, ContainsALetterFilter i ContainsNumberFilter (wiem, że przykłady troche z d*!@ :D).

Z racji, żę każda z nich implementuje Filter to mozesz zrobić np kolekcje(ArrayList np) filtrów i za ich pomocą filtrować jakiś string, obiekt, whatever :) filtr tylko zwroci true/false czy walidacja się udała

Gdybyś nie miał interfejsu to nie mógłbyś zrobić tego "zestawu filtrów" którymi dane słowo/obiekt filtrujesz. (no mógłbyś zrobić Object ale.. :D)

edytowany 2x, ostatnio: azalut
0

Sorry za złotego szpadla, ale to najlepszy zbiór informacji o interfejsach na tym forum, nie chciałem otwierać nowego. Skoro każdy już wie, czym jest interfejs, to może ktoś napisać, kiedy stosować interfejs a kiedy klasę abstrakcyjną? Jak dla mnie teraz, skoro interfejsy mogą mieć metodę defaultową, to chyba klasy abstrakcyjne są zbędne, ale chętnie posłucham kogoś mądrzejszego.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4708
1

Klasa abstrakcyjna ma:

  • pola,
  • konstruktor, (który, może coś na siłe robić/ wymuszać).

Ale tak czy siak, to nie znaczy, że nalezy używać. Nnajlepiej używać najmniejszej konstrukcji spełniającej wymagania. (least power).


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:16 dni
  • Postów:3277
0

Klasa abstrakcyjna może dziedziczyć po innej klasie, może mieć pola, metody które na tych polach operują. Metoda oznaczona jako abstrakcyjna nie musi być koniecznie publiczna. Jest to też oczywisty sposób wskazania jak rozszerzać klasę.

Kopiuj
public abstract class NullSafeMap<K, V> extends HashMap<K, V>
{
    @Override
    public V get(Object key)
    {
        V value = super.get(key);
        if (value != null)
        {
            return value;
        }

        @SuppressWarnings("unchecked")
        K typedKey = (K)key;

        V createdValue = createValue(typedKey);

        put(typedKey, createdValue);
        return createdValue;
    }

    protected abstract V createValue(K key);
}

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.