Witam, może mi ktoś wytłumaczyć do czego są interfejsy?
Niby wiem co to jest i do czego służy, wiem że jest to taka umowa, że klasa implementująca taki a nie inny interfejs będzie implementowała wszystkie jego metody itd. ale po co pisać interfejs skoro np. może być to uwzględnione w projekcie aplikacji, że np. klasa "a" ma zawierać ma zawierać 3 metody o takich a nie innych nazwach?
Rozumiem, że interfejsy mają zastosowanie w aplikacjach liczących raczej setki niż dziesiątki klas czy tak?
Niby umiem tworzyć obiekty, pisać klasy rozumiem istotę klas abstrakcyjnych bo w metodach klasy abstrakcyjnej coś jest a tutaj nie ma nic, tylko deklaracja.
Byłbym wdzięczny za wytłumaczenie z punktu widzenia tworzenia dużej aplikacji.
Dodatkowo prosiłbym o jakiś namiar na projekt aplikacji w javie w którym mógł bym podejrzeć jak działa i do czego przydaje się np. obiektowość, interfejsy itd. małe przykłady oraz książki do nauki java tłumaczą jedynie zasadę działania a nie to jak dany element języka ułatwia programowanie czy też wspomaga wydajność aplikacji.
Nie bardzo rozumiem. Co to wg ciebie znaczy:
po co pisać interfejs skoro np. może być to uwzględnione w projekcie aplikacji, że np. klasa "a" ma zawierać ma zawierać 3 metody o takich a nie innych nazwach?
A jak byś chciał takie coś "wymusić"? Java to nie python i nie ma duck typingu. W javie kod się zwyczajnie nie skompiluje jeśli dany typ nie posiada odpowiedniej metody którą chcesz wywołać.
Interfejsy pozwalają ci na pracę z obiektami klas które nie istniały jeszcze kiedy dany kod pisano. Założmy że napisałeś sobie funkcje do sortowania i przyjmujesz jako argument List<T>
. Za 10 lat ktoś może napisać własną listę i o ile zaimplementuje ten interfejs to będzie mógł ją sortować twoją funkcją.
Bardziej obrazowo - może nie tyle co nie istnieją, ale nie wiesz co to będzie za klasa i w zasadzie nie powinno Cię to dużo obchodzić. Np. mamy Interface IDeviceConnection. Dalej mamy tam metodę Send, więc możemy stworzyć obiekt tego interfacu czyli IDeviceConnection devCon = CreateDevCon(); Teraz Metoda CreateDevCon zwróci obiekt który implementuje interface, ale może to być połączenie po ethernecie, a może to być po rs232 i Ciebie to nie interesuje, używasz obiektu implementującego dany interface. W przyszłości jak dojdzie połączenie po RS485 wpinanym w PCI-E, nie zmienisz linijki swojego kodu, tylko doimplemetuje się kolejną klase implementująca interface IDeviceConnection.
Mylisz pojęcie "umowa". Tu nie chodzi o umowę między programistami a umowę/kontrakt w kodzie. Mając obiekt implementujący interfejs zawsze możesz wykonać na nim pewne operacje które tenże interfejs gwarantuje. Np:
interface IDoable
{
void DoSomething();
}
class Car : IDoable
{}
class Pen : IDoable
{}
...
static void Test()
{
Pen pen = new Pen();
Car car = new Car();
Process(pen);
Process(car);
}
static void Process(IDoable obj)
{
obj.DoSomething();
}
To nieważne że Car i Pen w rzeczywistości nie mają ze sobą nic wspólnego. Implementując interfejs możemy patrzeć na obiekty typu Car i Pen jak na obiekty typu IDoable i wywoływać metody zapewniane przez interfejs. Na tym polega ta "umowa"- implementujesz interfejs więc będziesz posiadał metody które ten interfejs zapewnia.
EDIT: Ogólnie to uważał bym na pojęcia typu umowa, kontrakt etc. Faktycznie są to określenia mogące zamieszać osobie początkującej.
Dzięki interfejsom banalne robi się IoC/DI, a pośrednio dzięki wstrzykiwaniu zależności (czyli DI) łatwo robi się testy jednostkowe na mockach.
Dobra, widzę, że istnieje pewna przepaść pomiędzy mną (osobą, która dopiero zaczęła rozumieć obiektowość choć nie do końca) a osobami pracującymi z tym na co dzień.
Może napiszę krótki przykład i prosił bym o jego rozbudowę tak abym jakoś to zrozumiał.
public interface Pojazd {
public void jazda(int predkosc);
public void stop();
}
public class Samochod implements Pojazd {
@Override
public void jazda(int predkosc) { }
@Override
public void stop() { }
public void drift() { }
}
public class Rower implements Pojazd {
@Override
public void jazda(int predkosc) { }
@Override
public void stop() { }
public double skok() { }
}
Dlaczego nie mogę napisać po prostu tak:
public class Samochod {
private void jazda(int predkosc) { }
private void stop() { }
private void drift() { }
}
public class Rower {
private void jazda(int predkosc) { }
private void stop() { }
private double skok() { }
}
Odpowiadając pamiętajcie, że dopiero tego się uczę. Pewnych rzeczy nie rozumiem, o wielu, może nawet banalnych nie pamiętam. Nie mam z tym do czynienia na co dzień żeby sobie utrwalić.
Wytłumaczenie dla początkującego: możesz mieć interfejs Pojazd z metodą Jedź(). Nie możesz stworzyć obiektu Pojazd, ale możesz mieć Samochód albo Rower, które implementują ten interfejs. I później, gdy sobie tworzysz listę pojazdów, to masz pewność, że każdy z nich będzie mógł jeździć. Do tej pory zachowanie jest w miarę jak z klasami abstrakcyjnymi. Plusem interfejsów jest to, że jedna klasa może implementować dowolnie wiele.
Ok, możesz, ale będziesz musiał wiedzieć, czy chcesz powołać obiekt Samochód, czy Rower. Może nie obchodzi Cię w programie czym będzie jechał bohater Twojej gry, ale, ważne, że będzie jechał więc mając interface Pojazd, powołujesz sobie obiekt tak: Pojazd pojazd = GetCurrentMachine(); i teraz możesz zacząć nim jechać tak: pojazd.jazda(100); Jeśli ktoś w grze doda np. quada, to Ty nie zmienisz swojego kodu. Inaczej miał byś ifa coś w stylu
Samochod sam = NULL;
Rower row = NULL;
if(GetCurrentMachine().GetClassName() == Samochod)
{
sam = GetCurrentMachine.GetSamochod();
}
...
if(sam != NULL) ....
Co nie jest ani eleganckie, a dwa jak dojdzie ci właśnie quad czy motorówka, będziesz musiał wszędzie to poprawić. Jak to mawiają Amerykanie - "Można żyć, bez coca coli, ale po co ? ", tak samo jest z interfacami. Dodatkowo jeżeli masz zrobic klase motorówki, a nie chcesz wchodzić w kod który startuje ten pojazd, bo kod ma 10lat i nikt go nie chce ruszać, ani się zagłębiać (albo nie można bo zamknięty moduł), to implementujesz wyznaczony interface.
datdata napisał(a):
Wytłumaczenie dla początkującego: możesz mieć interfejs Pojazd z metodą Jedź(). Nie możesz stworzyć obiektu Pojazd, ale możesz mieć Samochód albo Rower. I później, gdy sobie tworzysz listę pojazdów, to masz pewność, że każdy z nich będzie mógł jeździć. Do tej pory zachowanie jest w miarę jak z klasami abstrakcyjnymi. Plusem interfejsów jest to, że jedna klasa może implementować dowolnie wiele.
O takie wyjaśnienie mi chodziło. Po przeczytaniu kilku przykładów w internecie stworzyłem sobie w głowie błędne założenia i dopiero Tobie udało się je wyprzeć.
@luis W podanym przykładzie jak najbardziej dobrze rozumujesz- Rower i Samochód dziedziczą po klasie Pojazd ponieważ oba są pojazdami. Ale w podanym przeze mnie przykładzie- po jakiej wspólnej klasie miałby dziedziczyć Pen i Car? Jak sprawić by oba obiekty dostarczały podobnej funkcjonalności mimo że konceptualnie są dwoma różnymi "rzeczami"? W takich sytuacjach w gre wchodzą interfejsy. Poza tym pozwolę sobie wkleić fragment mojej wypowiedzi z innego tematu:
(...)na początu nauki programowania warto wykazać trochę pokory i przyjąć zasadę "Wiem że nic nie wiem". Początkujący programiści często zapominają albo i nie wiedzą że to czego się uczą to jedynie mechanizmy, a sens używania tych mechanizmów przyjdzie z czasem. Przykład z (...)- skupiasz się na bardzo małym kontekście zamiast skupiać się na mechanizmie który poznajesz. To może wydawać się nie mieć sensu ale uwierz że jak najbardziej ma i takie mechanizmy nie istnieją bez powodu. Po prostu z czasem to "zaskoczy" i sam sobie uświadomisz jakie to banalne.