Czy muszę nadpisać wszystkie metody?

0

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ść?

0

Nie, co najwyzej mozesz te metody zostawic puste

2

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
    }
}
0

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.

3

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

0

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

0

@niepamietamloginu: na pewno musisz implementowac BlockingQueue? Czemu tak?

0

Niestety. Zostało to narzucone w treści zadania.

0

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.

0

Możesz też spróbować dziedziczyć z klasy AbstractQueue<T> i wtedy nie musisz nadpisywać metody remove(Object) i paru innych.

1

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.

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