Skip to content

Witaj w Świecie Jutra!

  • Technologie jutra
  • Sprzęt jutra
  • Aplikacje jutra
  • Programowanie
  • Księga Drogi
  • Renowacja
  • Różności
  • Archiwum
  • Autor
  • Home
  • Wszystko
  • Programowanie funkcyjne – Odniesienia do metody
  • Programowanie
  • Wszystko

Programowanie funkcyjne – Odniesienia do metody

Jakub Raczkowski 25 marca 2024

W poprzednim wpisie wyjaśnialiśmy sobie czym tak właściwie jest ta lambda w Javie i wyszło nam, że to taka na szybko stworzona metoda w na szybko stworzonej klasie w oparciu o jakiś interfejs funkcyjny. Ale co gdyby – czysto hipotetycznie! – owa potrzebna nam metoda już gdzieś w jakiejś klasie istniała i nie trzeba byłoby jej pisać od zera?

Zacznijmy od czegoś tak prostego jak tylko się da. Czegoś, co uczymy się już pierwszego dnia naszej przygody z Javą (i chyba z każdym innym językiem programowania, tylko w mniej lub bardziej zmienionej postaci):

System.out.println(„Hello world!”);

Co robi ten kawałek? Wiadomo – wyświetla napis w nawiasach: Hello world! bezpośrednio w konsoli. Ale jak dokładnie to się dzieje?

  • Co to jest ten „System”?!
  • Co to jest ten „out”?!!
  • Co to jest ta funkcja „println()”?!!!
System jest klasą, która „zagląda” level wyżej niż sam projekt.

System, to klasa, która nie tworzy żadnych obiektów (jej konstruktor jest prywatny), za to posiada szereg statycznych metod, które dotyczną nie tyle samej aplikacji, którą budujemy, co systemu – platformy na której się ona znajduje. Dla przykładu:

  • System.currentTimeMillis() wyświetla ilość milisekund która upłynęła od „daty zero” (1 stycznia 1970, data uważana powszechnie za początek ery systemów unixowych)
  • System.gc() z kolei ma w założeniu uruchamiać „odśmiecarkę” JVM (ang. „garbage collector”), ale, że GC ma własne widzimisię to de facto – ta metoda nie robi nic
  • System.exit(0) kończy działanie aplikacji (dla wartości 0 kończy naturalnie, a dla 1 zupełnie jakby wyskoczył jakiś błąd)
„out” to statyczna zmienna typu PrintStream, już podłączona do konsoli

Klasa System ma również kilka statycznych zmiennych odnoszących się do konkretnych obiektów z których metod możemy korzystać:

  • System.out.println() operuje na obiekcie „PrintStream out” dzięki któremu możemy wypisać dowolny tekst w konsoli
  • System.err.println() działa podobnie jak System.out.println() ale służy do wyświetlania błędów, więc jej wyniki są zawsze w kolorze czerwonym
  • System.in to obiekt typu InputStream – uruchamiany jest strumień wejściowy w konsoli, ale inny obiekt musi go jakoś obsłużyć, np. Scanner
PrintStream printStream = new PrintStream(System.out);
printStream.println("Tak również wyświetlimy tekst w konsoli");

Scanner scanner = new Scanner(System.in); //a tak otworzymy strumień wejściowy
int i = scanner.nextInt(); //i przypiszemy wprowadzoną liczbę do zmiennej i 

Dobrze, skoro już jest jasne jak działa popularny System.out.println() to teraz zastanówmy się czym do cholery jest poniższy kawałek:

System.out::println

Dwa sposoby na osiągniecie tego samego efektu. Który lepszy?

Jak widać na obrazku powyżej, jest to coś powiązane z lambdą, ale inne – jeszcze krótsze. Zaś efekt działania pozostaje ten sam – tu i tam tekst wyświetla się w konsoli.

Wróćmy do kroków niezbędnych do utworzenia lambdy z poprzedniego odcinka i dodajemy do tego ten nowy kawałek z podwójnym dwukropkiem:

Jak powstaje lambda + jak powstaje odniesienie

Wyraźnie widać, że początek jest ten sam. Robimy klasę anonimową, a potem po kolei usuwamy zbędne elementy aż zostaje „goła” lambda. Ale czasami, tylko w sprzyjających warunkach, możemy pójść inną drogą – odnosząc się do już gotowej metody.

A jakie warunki są „sprzyjające”?

Po pierwsze musimy wybrać taką metodę która jest bliźniaczo podobna do metody zadeklarowanej w interfejsie z którego korzystamy. O ile nazwy mogą się różnić to już:

  • typ zwracany MUSI być ten sam
  • liczba użytych parametrów MUSI się zgadzać
  • typy użytych parametrów MUSZĄ być dokładnie takie same
  • no i oczywiście ta metoda musi robić to co nam akurat potrzeba
Od teraz kapłanów mogę tworzyć jeszcze szybciej!

Największym problemem w zrozumieniu jak działa method reference jest to, że nie widać tam żadnych zmiennych. Nawet w lambdzie, pierwszym co robimy jest stworzenie sobie na szybko jakiejś zmiennej:

Interface interface = zmienna -> zmienna.jakaśMetoda();
interface.metodaInterfejsu(tuWrzucamyParametrZmienna);

Pamiętajmy na jakiej zasadzie działa wyrażenie lambda – ta tymczasowo stworzona zmienna jest pozbawiona typu tylko i wyłącznie dlatego, że jest on kopiowany z metody interfejsu. Odniesienia działają w ten sam sposób, tylko, że jeszcze bardziej.

Kiedy wpiszemy np. String::trim, czyli metodę klasy String, która pobiera jeden ciąg znaków, usuwa z niego spacje z przodu i z tyłu, a następnie go zwraca, JVM sprawdza, czy metoda naszego interfejsu typującego ma podobną sygnaturę:

  • zwraca String? zgadza się!
  • ma jeden parametr? zgadza się!
  • ten parametr jest typu String? zgadza się!

Wszystko ok, można użyć odniesienia do metody. Albo przeciwnie – coś nie bangla i trzeba jak jaskiniowiec korzystać ze zwykłej lambdy.

Kiedy już nauczymy się tworzyć odniesienia do metod, nasz kod stanie się jeszcze bardziej zwięzły – nie dość, że będzie krótszy to jeszcze od razu będzie widać co tam się dzieje.

Interface interface = String::trim;
interface(tuWrzucamyJakiśString);
Kawałek „::new” po prostu tworzy obiekt w oparciu o dany input.
Różne efekty użycia odniesień.

forEach()

Odniesienia do metod są bardzo często spotykane w Stream API (o tym w kolejnym odcinku) oraz w metodzie forEach() która jest estetycznym zamiennikiem zwykłego iterowania po elementach kolekcji/tablicy znanego z Javy 5.

Wcześniej trzeba było podać typ elementów kolekcji, zadeklarować zmienną i podać nazwę kolekcji w której będziemy przebierać. Następnie blok {} i możemy w końcu wrzucać elementy do pasujących nam metod. Sporo tego, szczególnie jeśli chcemy tam użyć tylko jednej metody. Z pomocą przychodzi właśnie funkcja forEach sparowana z method reference:

Nie wiem jak wy, ale ja od dzisiaj znacznie rzadziej będę korzystał z domyślnej iteracji.

Teoria teorią, ale jak to ogarnąć na co dzień?

Wyobraźmy sobie przeciętnego człowieka: głowa, 2 ręce, 2 nogi, brzuch, tyłek i tak dalej. Stwórzmy sobie obiekt takiego człowieka (Person) w kodzie, niech jego klasa implementuje interfejs Living z jedną metodą do() czyli „zrób”:

Living person = new Person();
person.do();

Podsumujmy: mamy człowieka i chcemy, żeby coś zrobił. Używając normalnej lambdy musielibyśmy za każdym razem pisać co dokładnie chcemy żeby gościu wykonał. Ale korzystając z odniesienia do (już istniejącej) metody wystarczy, że podamy klasę gdzie ta metoda się znajduje i jej nazwę:

Living p1 = Frog::jump;
Living p2 = Cook::prepareDinner;
Living p3 = Sleep::haveNap;
Living p4 = Animal::eat;
Living p5 = Rock::standStill;
Living p6 = Job::work;
Living p7 = Rezus::gibaj;


Tak jak z każdym nowym skillem, kluczem do wprawy jest regularna praktyka, ale tym zajmiemy się w następnym odcinku – poświęconym strumieniom, czyli zagadnieniu gdzie lambdy i odniesienia pojawiają się w ilościach hurtowych.

Na dzisiaj tyle, kod z tego odcinka znajdziecie na moim GitHubie.

Tags: functional programming

Continue Reading

Previous: Programowanie funkcyjne – Lambda
Next: Programowanie funkcyjne – Strumienie (1/2)

Related Stories

Mageege Moon104 – test niskoprofilowego mechanika
  • Sprzęt

Mageege Moon104 – test niskoprofilowego mechanika

11 marca 2025
Przebranżowienie cz.4
  • Programowanie

Przebranżowienie cz.4

27 lutego 2025
Smartfon Jutra
  • Sprzęt

Smartfon Jutra

15 lutego 2025

Ze świata

  • Antyweb
  • Kwantowo
  • Dwóch po dwóch
ChatGPT stał się jeszcze lepszy. Oto nowy i do tego tani plan
Karta SIM bez rejestracji - czy to jeszcze możliwe i… czy ma sens?
Koniec balu. O te karty NVIDII będzie trudniej na rynku. Dużo trudniej
Dowiedz się jak AI pomaga w nauce! clickON to bezpłatne warsztaty nie tylko dla najmłodszych
Napakowana lista nowości HBO Max. Przezabawna trylogia i wiele więcej
Jak stworzyć miasto przyjazne rowerom? Paryż mówi to jasno
Samsung zaskoczy swoich fanów. Przecieki odkrywają sekret nowych flagowców
Twórca ChatGPT coś kombinuje. Czym jest Projekt Agora?
Elon Musk nie ma powodu do radości. Użytkownicy zgłaszają problemy
Słucham tego zamiast książek i podcastów. Ty też powinieneś spróbować
ChatGPT z dużą nowością. Przyda się, jeżeli często korzystasz
Powstał cukier doskonały. Niskie kalorie, brak wyrzutu insuliny
Windows Vista umarł doszczętnie. Microsoft wyciągnął wtyczkę
Internet mobilny w Plus – najlepsze oferty na styczeń 2026
Windows z poważnym błędem. Może ci nie działać podstawowa funkcja
Używasz tych słuchawek? Zrób to jak najszybciej dla własnego bezpieczeństwa
Gmail jeszcze nigdy nie był tak wygodny. Zastanów się dobrze, nim aktywujesz
Co dalej z "amerykańskim" smartfonem Trump Mobile? Politycy reagują
WhatsApp z fantastyczną zmianą. Mała rzecz, a ucieszy miliony
Wszyscy o nim mówią. Wyczekiwany hit już na Netflix
To by było na tyle, jeśli chodzi o możliwość ugody
Ocalić od zapomnienia
Ostatni kwant
ALH 84001 – meteoryt, o którym mówiono nawet w Białym Domu
HESS zarejestrował kosmiczny elektron o niespotykanej energii [Phys. Rev. Lett.]
Matka ciemnej materii – recenzja biografii “Vera Rubin. Życie”
Satelita, który zerwał się ze smyczy
Wiadomość od Carla Sagana do przyszłych eksploratorów Marsa
Ile najdłużej może trwać zaćmienie Słońca?
Nowa największa liczba pierwsza ma ponad 41 milionów cyfr [GIMPS]
30 lat konsoli PlayStation – Odcinek #130
Omawiamy serię The Walking Dead (gość: Stary Gracz)
Nikt nie potrzebuje cienkich smartfonów – Odcinek #129
To ostatni dzwonek na kolekcjonowanie gier i filmów
Najlepsza relacja z PGA 2025 (Poznań Game Arena)
Bumblebee wśród klawiatur. Marvo Meqa 80W – recenzja
Pierwsze spotkanie z Omoda 7 Super Hybrid
Logitech MX Master 4, Wednesday, 1670 sezon 2 – Odcinek #128
Tani pad, który chciał być jak DualSense. Test Monka Contra GT-96
Secret Service i prasa komputerowa w Polsce – Odcinek #127

To może cię zainteresować:

Mageege Moon104 – test niskoprofilowego mechanika
  • Sprzęt

Mageege Moon104 – test niskoprofilowego mechanika

11 marca 2025
Przebranżowienie cz.4
  • Programowanie

Przebranżowienie cz.4

27 lutego 2025
Smartfon Jutra
  • Sprzęt

Smartfon Jutra

15 lutego 2025
Czym jest Swagger?
  • Programowanie

Czym jest Swagger?

22 lipca 2024
  • Technologie jutra
  • Sprzęt jutra
  • Aplikacje jutra
  • Programowanie
  • Księga Drogi
  • Renowacja
  • Różności
  • Archiwum
  • Autor
Copyright © All rights reserved. | DarkNews by AF themes.