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

Praktyka: klasy i interfejsy

VPS Starter Arubacloud
0 głosów
301 wizyt
pytanie zadane 2 grudnia 2018 w Java przez itcloud Gaduła (3,380 p.)
Żaden kurs tego nie tłumaczy a skupia się na teorii i wałkuje w kółko te same tematy typu: czym jest klasa, czym jest interfejs i jakie różnice między nimi i koniec.

A jak wygląda praktyka?

Dla mnie klasa to zbiór metod i właściwości. Kluczowe są tutaj dla mnie METODY, konkretne zapisy całej logiki, czyli jak dana funkcja ma działać!!! Konkretny kod, prawda?

Interfejs to dla mnie tylko nazwy, nazwy metod czyli jeśli impltementuję taki interfejs, to NIE MAM LOGIKI jeszcze a mam tylko informację, z jakich NAZW funkcji mogę korzystać.

Chyba że ja czegoś nie rozumiem ? Może te nazwy to też konkretne już mechanizmy które się w tych nazwanych metodach kryją?

Bo często jest zapis:

Interfejs x = new Konstruktor_klasy();

a np. jak ktoś tworzy interfejs:

 

interface{

    void show();

}

to daje mi do zrozumienia, że jak implementuję ten interfejs to mam u siebie mieć metodę(funkcję) show().

Ale gdzie ta logika od kogoś kto wcześniej taką metodę SHOW napisał ???? Bo w samym interfejsie PRZECIEŻ TEGO NIE MA!!!!

2 odpowiedzi

+3 głosów
odpowiedź 2 grudnia 2018 przez adrian17 Ekspert (344,100 p.)

Ale gdzie ta logika od kogoś kto wcześniej taką metodę SHOW napisał ???? Bo w samym interfejsie PRZECIEŻ TEGO NIE MA!!!!

Nie musi istnieć.

Raczej głównym użyciem interfejsów jest w argumentach metod:

interface Showable { void Show(); }
void SomeMethod(Showable item) {...}

Wtedy Showable pełni rolę prostego kontraktu: możesz przekazać do SomeMethod dowolną rzecz, pod warunkiem, że implementuje Showable (więc musi posiadać metodę Show()).

Ale gdzie ta logika od kogoś kto wcześniej taką metodę SHOW napisał ???? 

Niekoczniecznie. Jeśli na przykład używasz bibliotekę z metodą SomeMethod i interfejsem Showable, możliwe że nie istnieje ani jedna implementacja tego interfejsu - biblioteka może założyć, że tylko użytkownik biblioteki będzie implementował interfejs dla swoich klas.

komentarz 2 grudnia 2018 przez itcloud Gaduła (3,380 p.)
Czyli to nie jest tak jak nas uczą weszelkie kursy od podstaw, że implementując interfejs mam pamiętać o tym, tzn. nawet sam kompilator mi przypomni, ze mam posiadać metodę taką a taką, nawet jak będzie ona NIC NIE ROBIĆ ?

Bo przy klasach to ja widzę sens, że mam dziedziczyć klasę bo dzięki temu mam pewne mechanizmy do wykorzystania (nie muszę wywarzać otwartych drzwi), ew. klasę rozszerzam.

Jeśli mnie nie rozumiesz, to może posłużę się analogią do php: tam mogłem korzystać z funkcji, które ktoś napisał, z bibliotek, dawałem na początku skryptu include(..) i już.

W javie jak mowa o interfejsach to się gubię, bo co dzięki nim tak naprawdę zyskuję to w teorii wiem, że to kontrakty bla bla bla ale jak widzę korzystanie np. z kolekcji, list, to tam często po lewej stronie, jako typ referencji podaje się właśnie ten interfejs do diaska....
1
komentarz 2 grudnia 2018 przez mbabane Szeryf (79,280 p.)

 tzn. nawet sam kompilator mi przypomni, ze mam posiadać metodę taką a taką, nawet jak będzie ona NIC NIE ROBIĆ ?

Wiesz, że możesz to sobie po testować?

Zapisz to, uruchom program i zobacz co będzie się dziać.

interfejs w programowaniu obiektowym oznacza zachowanie (publiczne) obiektu. Wiele interfejsów ma końcówkę able, tłumacząc to na polski oznacza to zdolny - czyli obiekt jest zdolny do czegoś np. AutoClosable - obiekt zdolny do automatycznego zamknięcia w konstrukcji try-with-resources.

+3 głosów
odpowiedź 2 grudnia 2018 przez RafalS VIP (122,820 p.)
edycja 2 grudnia 2018 przez RafalS

Po pierwsze - spokojnie :D

Zmienna typu interfejsu moze przechowywać rozne obiekty klas implementujacych ten interfejs. To czesc polimorfizmu. Podstawy OOP.

Rola interfejsu to wyrazenie pewnego kontraktu. Interfejs to zbior metod publicznych, których implementacji wymagamy od klas implementujacych interfejs.

Pisząc funkcje ktora przyjmuje jakis interfejs jako argument mowimy, ze wymagamy od obiektow przekazywanych aby mialy zaimplementowane dane metody.

Gdybys typ argumentu byl konkretną klasa mógłbyś przeslac tylko obiekty tej klasy i jej pochodne. Przyklad:

void dodaj5(ArrayList<Integer> list){
   list.add(5);
}

Wymagamy arraylisty a wykorzystujemy jedynie fakt ze do tej listy można dodac integer, wiec nic nie stoi na przeszkodzie zeby podac tam inna liste np LiknedList, wiec zmieniamy typ na interfejs:

List<Integer>

Ale moment przeciez do kazdej kolekcji intow da sie dodac 5, wiec czemu sie ograniczac, moze kiedys będziemy chcieieli dodać 5 do HashSet'u

void dodaj5(Collection<Integer> collection){
   collection.add(5);
}

To samo tyczy sie innych klas. Od walidatora czegos wymagamy jedynie zeby potrafil zwalidowac to cos czyli zeby mial metode:

bool isValid(Cos cos);

To wymaganie wyrazamy w postaci interfejsu.

komentarz 2 grudnia 2018 przez itcloud Gaduła (3,380 p.)

To jest chyba cały szkopuł:

Rola interfejsu to wyrazenie pewnego kontraktu. Interfejs to zbior metod publicznych, których implementacji wymagamy od klas implementujacych interfejs.

Pisząc funkcje ktora przyjmuje jakis interfejs jako argument mowimy, ze wymagamy od obiektow przekazywanych aby mialy zaimplementowane dane metody.

Czyli podsumowując, jak daję w argumencie jakiejś funkcji typ interfejsu, nie oznacza to że nie będę mógł korzystać z już napisanych przez kogoś konkretnych metod, bo czesto to zbiór powiązań, że jakieś większe klasy będą implementowac właśnie ten interfejs, ten konrakt i dzięki temu będę mógł skorzystać z silnika, z jakiejś metody którą ktoś już wcześniej napisał ?

komentarz 2 grudnia 2018 przez RafalS VIP (122,820 p.)
List<Integer> list = new ArrayList<>();

list wskazuje na stworzony obiekt ArrayList. Roznoca jest taka, ze masz dostep tylko do tych metod ArrayListy ktore sa zapisane w interfejsie List.

ArrayList ar = list;

A teraz masz dostep do wszystkich metod klasy.
komentarz 2 grudnia 2018 przez itcloud Gaduła (3,380 p.)
Czyli pokazałeś, że mozna sobie utrudnić życie, ale w praktyce jest raczej na odwrót, korzystamy z interfejsu jako typu aby mieć JESZCZE WIĘCEJ dostępnych metod jak sam obiekt, z którego konstruktora korzystamy ???
1
komentarz 2 grudnia 2018 przez mbabane Szeryf (79,280 p.)

Wbrew pozorom nie jest to utrudnianie życia - owszem tracimy funkcjonalność, którą udostępnia tylko ArrayList, ale zyskujemy, że kod nie jest zależny od implementacji, bo ArrayList jest implementacją (konkretną) - klasa jest zależna od zachowania, w tym wypadku, List.

Kiedy dojdziesz do wniosku, że ArrayList jest nieodpowiednią strukturą danych do danego rozwiązania i będziesz chciał np. zrobić test czy np. lepszym wyborem będzie LinkedList (kolejna implementacja List<T>) to robisz tylko takie coś:

//SomeClass posiada konstruktor, który przyjmuje List)

SomeClass sc = new SomeClass(new ArrayList<>());  //korzystanie z AL

sc = new SomeClass(new LinkedList<>()); //cyk zmieniam na LinkedList 
//bez głębokiej ingerencji w kod SomeClass, a własciwie to nawet nie trzeba tam zagladac

 

komentarz 2 grudnia 2018 przez itcloud Gaduła (3,380 p.)
Kurcze, nie rozumiem tego, co to w praktyce daje. Powyżej pokazałeś, że zmieniasz sobie po prostu argumenty funkcji, robisz tak bo oba obiekty to tak naprawdę implementacja interfejsu LIST, tak ? Czyli równie dobrze w pierwszej linii typ SomeClass mógłby być po prostu List<>  ? Przepraszam, ale nie ogarniam tego.
1
komentarz 2 grudnia 2018 przez mbabane Szeryf (79,280 p.)

Nie martw się, też tego nie rozumiałem. Programuj próbuj czytaj a samo Ci to wejdzie nawet nie wiesz kiedy.

Czyli równie dobrze w pierwszej linii typ SomeClass mógłby być po prostu List<>  ? Przepraszam, ale nie ogarniam tego.

Sprawdź to ;D 

komentarz 2 grudnia 2018 przez itcloud Gaduła (3,380 p.)

Ok, sprawdziłem to i pupa.

Co jeszcze mam wykonać ?

import java.util.ArrayList;

class A{
    public A(List<> obj){
    }
}

public class test {
    A sc = new A(new ArrayList<>());  //korzystanie z AL
    sc = new A(new LinkedList<>());
}

 

 

komentarz 2 grudnia 2018 przez mbabane Szeryf (79,280 p.)
edycja 2 grudnia 2018 przez mbabane

Ok, sprawdziłem to i pupa.

To znaczy?

Pamiętaj że musisz podać typ jaki będzie przechowywała  Lista np.:

class A{
    public A(List<String> obj){
    }
}
komentarz 3 grudnia 2018 przez itcloud Gaduła (3,380 p.)

Fajnie wytlumaczył to Adas94 w innym wątku, dopiero znalazłem:

Interfejs natomiast to można rzec wyspecjalizowany zbiór zachowań (metod) do zaimplementowania dla danej klasy. Czyli tworzysz np klasę Człowiek i implementujesz w nim interfejsy (mówienie, poruszanie itd.). Teraz wyobraź sobie, że pracujesz nad funkcjonalnością poruszania się obiektów na mapie 2D. Nie będziesz wtedy inicjalizował obiektów klasy Człowiek, bo np Zwierzę czy tam Samochód też mogą się poruszać. Wtedy zainicjalizujesz obiekt typu danego interfejsu, a więc :

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. Chodzi o to, że działasz w tym wypadku na pewnym wyspecjalizowanym zagadnieniu danego obiektu (Poruszanie) nie mając dostępu do innych jego zachowań(innych metod nie dotyczących poruszania).

bo ja własnie tego nie rozumiem, że interfejsy to tylko kontrakty, zapisy typu "uzyj sobie metody o takiej nazwe" ale nie ma takiej metody "w środku". A gdzie ona jest? Sam ja napiszę, ale że nie chce pisać czegoś co już ktoś wcześniej napisał, to pewnie będzie w jakiejś KLASIE.

No i tu się właśnie gubię, szczególnie przy kolekcjach, nie ogarniam tej całej hierarchii. Że np. daję:

List<> cos = new ArrayList<>();

a List to jest interfejs, ArrayList to klasa. Tutaj jest to jasne, bo konstruktora ma klasa, nie interfejs. Czyli na podstawie powyższego wiem, że ta ArrayList-a powinna mieć metody zadeklarowane przez interfejs, wymuszone wręcz (mają one znaleźć się w ArrayLiście).

I teraz, nie piszę ich sam bo one są w klasie ArrayList bo ktoś wczesniej z programistów wpisał przy nagłówku tej klasy że ona implements List<E>   ? O taką pogadankę mi chodzi cały czas, jak to opisać.

1
komentarz 3 grudnia 2018 przez mbabane Szeryf (79,280 p.)

Interfejs logicznie rzecz biorąc wykorzystywany jest do tego by łatwo podmienić implementacje, z której coś korzysta.

Na przykładzie tego List<E> ->  ArrayList i LinkedList  te dwie klasy i różnią się od siebie diametralnie w działaniu. AL to jest typowa tablica dokładnie taka jak zadeklarowana w sposób ręczny, dostarcza tylko wysoce wydajne rzeczy, które robią ze zwykłej tablicy tablice dynamiczną (czyli zmieniającą swój rozmiar w trakcie działania programu).

LinkedList to jest lista dwukierunkowa.

I teraz robiąc tak:

//SomeClass posiada konstruktor, który przyjmuje List)
 
SomeClass sc = new SomeClass(new ArrayList<>());  //korzystanie z AL
 
sc = new SomeClass(new LinkedList<>()); //cyk zmieniam na LinkedList 
//bez głębokiej ingerencji w kod SomeClass, a własciwie to nawet nie trzeba tam zagladac

Diametralnie zmieniasz sposób w jaki przechowywane są dane w klasie SomeClass. Jednak dzięki zastosowaniu interfejsu sposób użycia tych konkretnych klas jest identyczny - mówimy tutaj tylko i wyłącznie o kodzie źródłowym, zapisanym przez programistę - bo program będzie działał zupełnie inaczej dla AL, a inaczej dla LL.

Poczytaj jeszcze o dwóch rzeczach mianowicie czym jest abstrakcji i hermetyzacja (chociaż tak po prawdzie abstrakcja to jest hermetyzacja). (Jeśli chodzi o abstrakcje nie mam tutaj na myśli klas abstract, tylko abstrakcję w kontekście programowania obiektowego).

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

poczytam o tej abstrakcji, rozumiem też co napisałeś że można zmienić w locie sposób implementacji, zamienić np. jsona na jakieś inny http request itd. ale tego już nie kumam:

Diametralnie zmieniasz sposób w jaki przechowywane są dane w klasie SomeClass.

 

mozesz to napisać inaczej, tak żeby zrozumiała Twoja druga połówka która zetknęła się tylko na chwilę z programowaniem na studiach ?

1
komentarz 4 grudnia 2018 przez mbabane Szeryf (79,280 p.)
Dobra. Taka sytuacja. Jest kierowca samochodu. Zakładamy, że każdy samochód ma kierownice, pedały i lewarek do zmiany biegów. Kierowca żeby móc jechać samochodem potrzebuje tych trzech rzeczy - inaczej może stwierdzić, że samochodem nie umie jeździć.

Teraz mamy dwa samochody, maluch i ferrari f60. W obu samochodach sterowanie jest identyczne, aby przyspieszyć trzeba dodać gazu, aby skręcać trzeba ruszać odpowiednio kierownicą, biegi zmienia się w taki sam sposób sprzęgło plus ruch lewarkiem itd. Nie ważne czy jest to maluch czy ferrari w obu te czynności wykonuje się w ten sam sposób.

Z punktu widzenia obsługi pojazdu oba niczym się nie różnią, jednak w samej jeździe już diametralnie.

Ferrari jest szybsze, lepiej wchodzi w zakręty, ale jest dwuosobowe i stosunkowo duże co utrudnia jazdę po mieście.

Maluch gorzej przyspiesza, jest toporny w prowadzeniu jednak jest mniejszy i wygodniej się nim poruszać po mieście.

I teraz dzięki temu, że kierowca umie obsługiwać samochód to tak na prawdę umie jeździć niemal każdym rodzajem auta i w zależności od sytuacji może bardzo łatwo zmienić typ pojazdu np. na szybszy i większy żeby wygodniej podróżować na długich dystansach, albo mały i ekonomiczny aby sprawnie poruszać się po mieście.

Samochód to interfejs. Maluch i Ferrari to implementacje interfejsu - konkretne klasy. Stosując interfejs nie trzeba uczyć, czegoś co z niego korzysta, jak ma używać konkretnej implementacji.
komentarz 4 grudnia 2018 przez itcloud Gaduła (3,380 p.)
Czyli implementacje interfejsu (tego typu interfejsowego) to tak naprawdę to co na prawo, ten konstruktor klasy? Czyli te klasy muszą w danym momencie mieć zaimplementowane dane metody, o których wyraźnie mówi interfejs, czyli defacto przy deklaracji takich klas na pewno pojawia się słówko IMPLEMENTS interfejs   (gdzie interfejs to własnie ten typ zmiennej jak niżej:)

Samochod zmienna = new  Ferari();     //klasa Ferrari implementuje interfejs samochod, czyli  moze miec mnostwo metod ale na pewno te ktorych wymaga Samochod ?

A jak to się ma w końcu do tego przekazywania w argumentach?
1
komentarz 5 grudnia 2018 przez mbabane Szeryf (79,280 p.)

Ferrari implementuje interfejs samochod, czyli  moze miec mnostwo metod ale na pewno te ktorych wymaga Samochod ?

Tak, to jest defacto wymagane przez samą Javę jak coś implementuje interfejs i nie ma wszystkich metod to nastepuje blad kompilacji.

A jak to się ma w końcu do tego przekazywania w argumentach?

Deklarujac ze metoda/konstruktor przyjmuje typ interfejsowy jest ona jak ten kierowca. Kierwocy jest obojetne czy dostaje ferrai czy malucha, z jego punktu widzenia samochod ma miec kierownice, pedaly i lewarek do biegów.

Po programujesz wiecej to to zrozumiesz.

konstruktor klasy

Konstruktor to konstruktor i nie mieszaj tym sobie. Masz interfejs i klasę, która implementuje ten interfejs. Sam konstruktor nie ma nic do tego.

Reszta się zgadza.

Podobne pytania

+1 głos
3 odpowiedzi 1,050 wizyt
pytanie zadane 3 listopada 2018 w Java przez k222 Nałogowiec (30,150 p.)
0 głosów
1 odpowiedź 541 wizyt
pytanie zadane 15 września 2016 w C i C++ przez Tadeusz Jasińska Nowicjusz (190 p.)
0 głosów
2 odpowiedzi 1,503 wizyt

92,454 zapytań

141,262 odpowiedzi

319,089 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...