Dobry wieczór. Właśnie piszę klasę implementującą kolejkę cykliczną. Klasa ta implementuje interfejs BlockingQueue<E>, a przez to jeszcze kilka innych. Problem w tym, że nadpisałem kilka potrzebnych mi metod, jednak kompilator wyrzuca, że mam nadpisywać jeszcze kolejne. Wychodzi na to, że potrzebne czy nie (nie potrzebuję np. remove(Object o) z BlockingQueue<E>, bo wystarczy mi remove() z Queue<E>), ale musiałbym nadpisać metody ze wszystkich interfejsów. A to, delikatnie mówiąc, jest bez sensu. Czy istnieje jakiś sposób, by to obejść?
Czy muszę nadpisać wszystkie metody?
- Rejestracja: dni
- Ostatnio: dni
- Postów: 54
- Rejestracja: dni
- Ostatnio: dni
- Postów: 13
Nie, co najwyzej mozesz te metody zostawic puste
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Space: the final frontier
- Postów: 26433
Jeśli implementujesz jakiś interfejs to MUSISZ implementować wszystkie jego metody. Inaczej nie miałoby to sensu! Przecież ktoś teraz może wziąć tą twoja klasę TwojaKlasa i zrobić:
BlockingQueue<String> queue = new TwojaKlasa<>();
queue.remove(cośtam);
I co teraz? Możesz zostawić puste implementacje, albo lepiej rzucać jakies NotImplementedError czy coś, ale to też bardzo biedne rozwiązanie.
Niemniej normalnie to się robi jednak jakąś delegacje -> masz swoją klasę która ma w sobie obiekt jakiejś standardowej kolejki. Nadpisujesz metody które cię interesuję, a resztę metod delegujesz do tej kolejki którą masz pod spodem:
class MojaKolejka<T> implements Queue<T>{
private final queue = new LinkedList<>();
@Override
public boolean add(T element){
// jakaś nasza specjalna logika
return queue.add(element);
}
@Override
public boolean offer(T element){
return queue.offer(element); // goła delegacja
}
}
- Rejestracja: dni
- Ostatnio: dni
- Postów: 54
Rozumiem. Zostawienie tych metod nie wydaje mi się bezpiecznym rozwiązaniem, ale chyba tak zrobię (lub wewnątrz nich wywołam ich przeciążone odpowiedniki). Pytanie zadałem, bo wspomniane przez @Shalom zastosowanie metody remove(Object) wydaje mi się absolutnie bez sensu. W kolejce cyklicznej mogę usunąć tylko element będący głową, a nie wybrany przeze mnie.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Space: the final frontier
- Postów: 26433
To nie ma znaczenia, bo implementujesz jakiś OGÓLNY interfejs! Czyli mówisz ze twoja klasa dostarcza taką funkcjonalność. Zasada L z SOLID się kłania. Jeśli chcesz mieć KolejkęCykliczną to zrób interfejs CyclicQueue<T> który ma tylko te metody które mają sens dla tej kolejki. Tutaj znowu kłania się Interface Segregation Principle. Po co chcesz implementować BlockingQueue<E> skoro twoja klasa w ogóle do tego interfejsu nie pasuje? o_O
- Rejestracja: dni
- Ostatnio: dni
- Postów: 54
Problem w tym, że muszę dziedziczyć po BlockingQueue<E>, więc stworzenie dodatkowego interfejsu nie zmieni mojej sytuacji, bo i tak muszę przesłonić wszystko. Prawdopodobnie zostanę przy wypisaniu wszystkich metod, wywoływaniu metod mających sens wewnątrz metod "bezsensownych" i oznaczeniu tych drugich jako "depracated".
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
- Postów: 3573
@niepamietamloginu: na pewno musisz implementowac BlockingQueue? Czemu tak?
- Rejestracja: dni
- Ostatnio: dni
- Postów: 54
Niestety. Zostało to narzucone w treści zadania.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Space: the final frontier
- Postów: 26433
Ale właściwie czemu uważasz że np. usuwanie losowego elementu "nie ma sensu"? Bo nie da sie tego wykonać w O(1)? LinkedList też na to pozwala, mimo że też w praktyce tylko head i tail można usunać w O(1), a losowe usuwanie to O(n).
Jeśli masz w treści zadania ze to ma być BlockingQueue to musisz zaimplementować wszystkie metody.
- Rejestracja: dni
- Ostatnio: dni
Możesz też spróbować dziedziczyć z klasy AbstractQueue<T> i wtedy nie musisz nadpisywać metody remove(Object) i paru innych.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Stacktrace
- Postów: 6823
Słowo klucz – delegacja. Zamiast samodzielnie implementować wszystkie metody, wydeleguj je do istniejącej implementacji:
class MyCyclicQueue<T> implements BlockinigQueue<T>, CyclicQueue<T> {
private final BlockinigQueue<T> delegate;
public CyclicQueue(BlockinigQueue<T> delegate){
this.delegate = delegate;
}
public boolean add(T t){
return delegate.add(t);
}
}
Do tego zdefiniuj interfejs CyclicQueue, który będzie zawierał tylko metody, które masz zamiar zaimplementować samodzielnie – z uwzględnieniem odpowiednich nazw. Nadal nie będzie to 100% SOLID, ale już będzie lepiej.