Luty 22, 2018

Funkcje w języku java

Funkcje w języku java

Cześć, w poprzednich lekcjach kursu cały nasz napisany kod mieścił się w jednej w funkcji zwanej main – głównej. Oznaczało to, że po uruchomieniu programu wykonywał się kod zapisany między klamrami funkcji main, tzn.:

package com.company;


public class Main {

    public static void main(String[] args) {
        
        //Ten kod wykonuje się przy starcie programu

    }
}

Nasuwa się jedno pytanie, czy możemy tworzyć własne funkcje? Odpowiedź jest prosta, tak. Jest to nawet wskazane, żeby dzielić kod, na takie segmenty, które są odpowiedzialne za daną czynność.

Funkcje

Czym są w ogóle funkcje? Możliwe, że kojarzysz to zagadnienie z lekcji matematyki. Są to podobne zagadnienia, w przypadku matematyki funkcja przyjmuje argumenty (np. x)„po przejściu” tego x przez funkcję otrzymujemy wynik tzn. y.

Zasada w programowaniu jest podobna. Tworząc funkcję, możemy zdecydować czy ma przyjmować argumenty (wspomniany wcześniej x w matematyce), ale tak naprawdę nie musi. Możemy zdecydować co ma zwracać (czyli jak wynik „wypluwać”), chociaż takowej operacji nie musi wykonywać.

Podsumowując, funkcje są blokami operacji, które mogą zostać wykonane poprzez jej wyłowanie (zawołanie: ej funkcjo X, chodź to zrobisz!). Może przyjmować argumenty i zwracać wynik – jednak podkreślam nie musi!

Deklaracja funkcji

Gdy mamy już trochę suchej teorii czym jest funkcja, przejdźmy do realnego przykładu w programowaniu. Nauczymy się deklarować funkcję, o to krótki schemat jak buduję się funkcję:

typ_zwracany nazwa_funkcji(argumenty){
  //ciało funkcji
  //czyli co ma się wykonać
}

Typy zwracane i argumenty

Znasz już typy danychsą to typy, które może zwracać funkcja. Dodatkowo w ten skład wchodzi również typ void (co oznacza nieważny)Poniżej zapiszemy sobie kilka przykładów implementacji funkcji dla kilku typów.

Co do argumentów, to dzięki nim możemy wprowadzać wartości do funkcji, na których będziemy mogli pracować w ciele funkcji. Np. możemy podać zestaw liczb i obliczyć dla nich odchylenie standardowe.

Warto na wstępie zaznaczyć, że funkcja zwraca wartość za pomocą słówka kluczowego return.

void

Tak jak wyżej napisałem, wykorzystanie tego typu oznacza, że funkcja ma za zadanie wykonanie danej operacji zamiast dać nam wynik.

Zapiszmy funkcję, przez której wywołanie, wyświetli nam się na ekranie klasyczny napis „Hello 1024kb.pl!”.

package com.company;


public class Main {

    public static void hello(){
        System.out.print("Hello 1024kb.pl!");
    }

    public static void main(String[] args) {

        hello();

    }
}

Na ekranie konsoli pojawia się nam napis, ponieważ wywołaliśmy funkcję hello().

Jak zauważyłeś metoda, która jest utworzona w main musi być statyczna (static), aby mogła być wywołana w metodzie main.

Dodajmy teraz argument do naszej funkcji, np. imię:

package com.company;


public class Main {

    public static void hello(String name){
        System.out.print("Hello " + name + " 1024kb.pl!");
    }

    public static void main(String[] args) {

        hello("John");

    }
}

I teraz naszym oczom na ekranie konsoli pojawia się napis: Hello John 1024kb.pl. W deklaracji funkcji, w nawiasach dodaliśmy argument: typu String i o nazwie name. Teraz w ciele funkcji możemy go wykorzystywać poprzez wywołanie jego nazwy tzn. name.

Przy wywołaniu funkcji w main trzeba podać argument, już wedle uznania – ważne, żeby zgadzały nam się typy.

int

Kolejne przykłady funkcji pokażemy sobie na typie int. Znaczy to, że nasza funkcja może „wypluwać” wartość całkowitą. Stwórzmy sobię funkcję, która będzie podnosiła podany argument do kwadratu.

package com.company;


public class Main {

    public static int square(int number){
        int square = number*number;
        return square;
    }

    public static void main(String[] args) {

        System.out.println("Kwadrat liczby 3: " + square(3));

    }
}

Do zmiennej square przypisujemy kwadrat liczby number. Następnie za pomocą słowa return zwracamy wartość zmiennej. Możemy oczywiście zapisać to prościej:

package com.company;


public class Main {

    public static int square(int number){
        return number*number;
    }

    public static void main(String[] args) {

        System.out.println("Kwadrat liczby 3: " + square(3));

    }
}

Jeżeli działanie fukcji jest proste to naprawdę zachęcam do właśnie takiego zapisu.

Wypisaliśmy nasz obliczony wynik na ekran, możemy jednak przypisać zwracaną wartość do zmiennej w funkcji main i dopiero dalej na niej działać. Ilustruje to prosty przykład:

package com.company;


public class Main {

    public static int square(int number){
        return number*number;
    }

    public static void main(String[] args) {

        int result = square(5);
        int x = result - 1;

        System.out.println("5^2 - 1: " + x);

    }
}

W tym przypadku użyliśmy funckji square, aby obliczyła nam kwadrat liczby 5 i zapisała wynik do result. Następnie używaliśmy tej zmiennej w dalszej części programu

double

Zastosujmy teraz jako parametr tablicy, stwórzmy funkcję, która będzie obliczała średnią podanych liczb w tablicy. Tablicę jako parametr deklarujemy w prosty sposób, zacznijmy od stworzenia funkcji:

public static double average(double numbers[], int countOfNumbers)

Czyli deklarujemy funkcję o nazwie average, która zwraca typ double, a jej argumentami jest tablica o nazwie numbers oraz liczba int oznaczająca ilość elementów w tablicy.

Jak zauważyłeś, aby można było użyć tablicy jako parametru wystarczy dodać nawiasy kwadratowe po nazwie parametru.

Stworzymy sobie teraz ciało funkcji, która ma za zadanie liczyć średnią. Na początku zadeklarujmy sobie zmienną, która będzie przechowywała sumę liczb. Wyzerujmy ją od razu, abyśmy mogli do niej dodawać.

double sum = 0.0d;

Następnie potrzebujemy zsumować liczby, powinieneś już wiedzieć, że przyda nam się do tego pętla np. for.

for(int i=0; i <countOfNumbers; i++){
            sum += numbers[i];
}

Czyli jak widać do zmiennej sum, sumujemy po kolei elementy tablicy numbers podanej jako argument. Teraz wystarczy obliczyć średnią i ją zwrócić.

return sum / countOfNumbers;

Czyli zwracamy średnią liczb tzn. sumę podzielić przez ilość liczb. Kod całej funkcji prezentuje się następująco:

public static double average(double numbers[], int countOfNumbers){
        double sum = 0.0d;

        for(int i=0; i <countOfNumbers; i++){
            sum += numbers[i];
        }

        return sum / countOfNumbers;
}

Czas na wywołanie funkcji w funkcji main, obliczymy sobie średnią dla podanych wartości w tablicy.

Zadeklarujmy sobie tablice double i wpiszmy do niej wartości, np. w ten sposób:

double [] dane = {1.0, 1.5, 1.6, 1.9};

Stwórzmy następnie zmienną, do której zapiszemy wynik. Wywołanie funkcji jak już wiesz odbywa się poprzez jej nazwę i podanie argumentów.

double srednia = average(dane, 4);

Jak zauważyłeś przy wywołaniu funkcji i używaniu tablicy wystarczy napisać samą nazwę tablicy, już bez żadnych dodatkowych znaczków. Drugim argumentem, tak jak ustaliliśmy przy deklaracji funkcji jest ilość liczb w tablicy.

Na koniec wypiszmy sobie wynik na koniec, i voila – o to nasz cały kod.

package com.company;


public class Main {

    public static double average(double numbers[], int countOfNumbers){
        double sum = 0.0d;

        for(int i=0; i <countOfNumbers; i++){
            sum += numbers[i];
        }

        return sum / countOfNumbers;
    }

    public static void main(String[] args) {

        double [] dane = {1.0, 1.5, 1.6, 1.9};

        double srednia = average(dane, 4);

        System.out.print("Średnia podanych liczb to: " + srednia);

    }
}

boolean

Dodatkowo możemy oczywiście skorzystać z typu boolean, czyli do zwracania true false. Takiego typu funkcję są bardzo przydatne, ponieważ po prawidłowo wykonanej operacji mogą zwracać true.

Stwórzmy sobię funkcję, która będzie sprawdzać czy liczba jest podzielna przez 3. Deklaracja takiej funkcji będzie wyglądać tak:

public static boolean isDividedByThree(int number)

Nie powinno być dla Ciebie już dużej filozofii, funkcja zwraca true/false, a jako argument przyjmuje liczbę typu całkowitą, którą będziemy „badać”. Tak więc prezentuje się ciało funkcji:

public static boolean isDividedByThree(int number){
        if(number%3 == 0){
            return true;
        }else{
            return false;
        }
}

Wszystko ładnie działa, jednak w przypadku funkcji możemy trochę skrócić nasz zapis – tzn. nie używać bloku else.

public static boolean isDividedByThree(int number){
        if(number%3 == 0){
            return true;
        }
        
        return false;
        
}

Blok else, nie jest potrzebny w tym przypadku, ponieważ jeżeli wejdziemy w blok if to automatycznie wykona się return true i przerwiemy działanie funkcji.

Możemy też skrócić nasz zapis poprzez pozbycię się klamerek, ponieważ możemy ich nie używać, gdy po if, else, elseif oraz pętlach for, while, do while występuje tylko jedna instrukcja.

public static boolean isDividedByThree(int number){
        if(number%3 == 0)
            return true;
        
        return false;
}

Opowiadałem jeszcze o operatorze ? (trójargumentowym) we wpisie o instrukcjach warunkowych.

public static boolean isDividedByThree(int number){
        return number%3 == 0 ? true : false;
}

Ale to już tylko jako ciekawostka, wszystkie rozwiązania są prawidłowe.

Wywołajmy sobie teraz ową funkcję i sprawdźmy jej działanie:

package com.company;


public class Main {

    public static boolean isDividedByThree(int number){
        return number%3 == 0 ? true : false;
    }

    public static void main(String[] args) {

        if(isDividedByThree(6))
            System.out.print("Liczba jest podzielna przez 3.");
        else
            System.out.print("Liczba nie jest podzielna przez 3.");

    }
}

Mając stworzoną funkcję typu boolean, możemy w bardzo fajny sposób jej później wykorzystywać w instrukcjach warunkowych, tak jak zrobiłem to wyżej. Oczywiście na ekranie pojawi się napis: „Liczba jest podzielna przez 3.”, ponieważ funkcja zwraca nam true czyli warunek if jest spełniony.

Podsumowując

Pokazałem Ci kilka przykładów zastosowania funkcji, poprzez funkcję typu int lub double, która ma obowiazek zwracać liczbę swojego typu, przez funkcję typu boolean, która zwraca nam prawdę lub fałsz, aż do typu void, który nie musi nic zwracać, jednak można kończyć pracę tej funkcji za pomocą słowa return;, nie zwracając już żadnej wartości.

Jeżeli wszystko było dla Ciebie jasne, zapraszam Cię do rozwiązania do poniższych zadań i sprawdzenia się czy, aby na pewno wszystko w 100% rozumiesz. W razie problemów pisz w komentarzu, a postaram się Ci pomóc.

Zrób to sam już teraz!

Wszystkie funkcje, które stworzysz na podstawie tych zadań wywołaj później w main i sprawdź ich działanie.

  1. Stwórz funkcję, do której będziemy przekazywać imię i nazwisko, a funkcja będzie miała za zadanie przywitać nas napisem: Witaj w programowaniu Jan Kowalski!
  2. Stwórz funkcję, która będzie obliczała odchylenie standardowe dla podanych liczb w tablicy jako argument.
  3. Stwórz funkcję, która będzie obliczała potęgę n dla podanej liczby tzn. x^n. 
  4. Stwórz dwie funkcję, pierwsza ma za zadanie obliczyć silnię dla podanej liczby, druga zaś ma sprawdzić czy podana liczba jest liczbą parzystą.