Do czego są interfejsy?

0

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.

0

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ą.

1

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.

1

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.

3

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.

0

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ć.

2

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.

0

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.

0
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ć.

0

@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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1