Zakończyłem jak na razie temat typów generycznych w Javie. Te trzy części tłumaczenia zastosowania typów ogólnych były potrzebne po to, abyśmy mogli teraz spokojnie wrócić do poprzedniego rozdziału na którym stanęliśmy. Możemy w końcu porównać sobie interfejs "Comparable" do poprzedniego i zobaczyć jak daleko idą te różnice.

INTERFEJS "COMPARABLE". KRYTERIUM OSADZONE W KLASIE

Pierwsza część prezentowała zastosowanie interfejsu "Comparator" do ustalenia filtru do sortowania. Jeśli potrzebny Wam jest taki filtr tylko na chwilę, ten zapis możecie stosować bez problemu. Natomiast drugi interfejs będący w tytule umożliwia osadzenie metody sortującej bezpośrednio do klasy, czyli tak, jak zwykle implementujecie interfejs do klasy. Nawet, jeśli jest możliwe korzystanie z interfejsu "Comparator" w klasie, to i tak nie będzie możliwe wywołanie jednoargumentowej postaci metody "sort" z klasy "Collections", gdyż ona "oczekuje" parametru będącego kolekcją przechowującą elementy typu "klasa implementująca interfejs "Comparable"". Nie wierzycie, to spróbujcie podstawić do klasy ten pierwszy i wywołać metodę "Collections.sort" z pojedynczym parametrem!

Przyglądając się składni tej metody (obrazek zamiast okna kodu z powodu problemów jakie stwarza "Joomla"):

Nagłówek metody "sort" dla "Comparable"

widzimy jednoznacznie, że metoda oczekuje listy której elementy implementują ten sam interfejs, który również on sam jest generyczny! Jak wspomniałem w trzeciej części o typach ogólnych, nawiasy kątowe można zagnieżdżać! Prościej rzecz ujmując, "Comparable" musi być tego samego typu klasowego co nasze elementy zawarte w kolekcji, a to, co oznacza "super" dla typów generycznych i jaką to robi różnicę przy "extends", zostawimy sobie na odrębny artykuł.

To jest główna przyczyna czemu wolałem na jakiś czas przerwać ten temat i wpierw wytłumaczyć Wam typy generyczne, bo teraz przynajmniej oswoiliście się z bardziej skomplikowanymi zapisami nagłówków metod i dalsze brnięcie w ten temat skutkowałoby nieustannym drapaniem się po głowie. Ostatnia rzecz przed przejściem do przykładu: tym razem metoda sortująca nosi nazwę "compareTo" i przyjmuje tylko jeden parametr podanego typu.

PRZYKŁAD KODU Z PORÓWNANIEM

Więcej informacji nie trzeba. Podsumujmy to kodem źródłowym z naszą książką i krótko skomentujmy:

  • KLASA "Main"
public class Main
{
	public static void main(String[] args)
	{
		new Launcher();
	}
}
  • KLASA "Book"
public class Book implements Comparable<Book>
{
	private final String title, author, publisher;
	private final int year;

	public Book(String author, String title, String publisher, int year)
	{
		this.author = author;
		this.title = title;
		this.publisher = publisher;
		this.year = year;
	}

	@Override
	public String toString()
	{
		return author + ". " + title + ". " + publisher + ", " + year;
	}

	@Override
	public int compareTo(Book book)
	{
		return year - book.year;
	}
}
  • KLASA "Launcher"
import java. util.ArrayList;
import java. util.Collections;

public class Launcher
{
	private ArrayList<Book> books;

	public Launcher()
	{
		createInstances();
		addBooks();
		printBooks();
		Collections.sort(books);
		printBooks();
	}

	private void createInstances()
	{
		books = new ArrayList<>();
	}

	private void addBooks()
	{
		books.add(new Book("Adam Mickiewicz", "Pan Tadeusz", "Aleksander Jełowicki", 1834));
		books.add(new Book("Gustaw Herling-Grudziński", "Inny świat", "Roy", 1951));
		books.add(new Book("Aleksander Głowacki", "Lalka", "Gebethner i Wolff", 1890));
	}

	private void printBooks()
	{
		System.out.println("\nWYPISYWANIE LISTY:");
		books.forEach(System.out::println);
	}
}

Oto pierwsza korzyść z korzystania z "Comparable": wszystko jest w jednym miejscu. Nie "rozłazi się" to dookoła kilku klas i tam, gdzie sortowanie dotyczy książek, znajduje się w klasie książki. I tak powinno być. Druga zaleta to możliwość uniknięcia getterów. Dostrzegliście, że w metodzie "compareTo" mogę spokojnie przedostawać się do danych składowych bezpośrednio? Krótszy kod, to zawsze lepszy kod, o ile tylko działa tak samo.


Cieszę się, że tym razem artykuł stał się krótszy i nie trzeba było tłumaczyć nie wiadomo ile. Podsumowując, "Comparable" piszecie w klasie definiując własny domyślny filtr do sortowania. "Comparator" natomiast stosujecie "lokalnie" na zewnątrz klasy kiedy w danym przypadku to musi być niestandardowe kryterium do sortowania.

PODOBNE ARTYKUŁY