JavaRush /Java Blogu /Random-AZ /Metodlar, onların parametrləri, qarşılıqlı əlaqə və həddi...

Metodlar, onların parametrləri, qarşılıqlı əlaqə və həddindən artıq yükləmə

Qrupda dərc edilmişdir
Birdaha salam! Son mühazirədə biz siniflər və konstruktorlarla tanış olduq və özümüzünkülərin necə yaradılacağını öyrəndik. Metodlar, onların parametrləri, qarşılıqlı əlaqə və həddindən artıq yükləmə - 1Bu gün biz üsullar kimi dərslərin ayrılmaz hissəsinə daha yaxından nəzər salacağıq. Metod proqramda bəzi əməliyyatları yerinə yetirməyə imkan verən əmrlər toplusudur. Başqa sözlə, metod funksiyadır; sinifinizin edə biləcəyi bir şey. Digər proqramlaşdırma dillərində metodlar çox vaxt “funksiyalar” adlanır, Java-da isə “metod” sözü daha populyarlaşıb :) Keçən mühazirədə, yadınızdadırsa, Cat sinfi üçün sadə üsullar yaratmışdıq ki, pişiklərimiz miyavlaya bilsin. və tullanmaq:
public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Jumping gallop!");
    }

    public static void main(String[] args) {
        Cat barsik = new Cat();
        barsik.age = 3;
        barsik.name = "Barsik";

        barsik.sayMeow();
        barsik.jump();
    }
}
sayMeow()jump()bizim sinifin metodlarıdır. Onların işinin nəticəsi konsola çıxışdır:
Мяу!
Прыг-скок!
Metodlarımız olduqca sadədir: onlar sadəcə mətni konsola çap edirlər. Lakin Java-da metodların əsas vəzifəsi var - onlar obyektin məlumatları üzərində hərəkətlər etməlidirlər . Obyekt məlumatlarının dəyərini dəyişdirin, onu çevirin, konsola çıxarın və ya onunla başqa bir şey edin. Mövcud metodlarımız obyektin məlumatları ilə heç nə etmir Cat. Daha aydın bir misala baxaq:
public class Truck {

    int length;
    int width;
    int height;
    int weight;

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
Məsələn, bir yük maşını təmsil edən bir sinifimiz var - Truck. Yük maşınının qoşqusunun uzunluğu, eni və hündürlüyü və çəkisi var (bu daha sonra lazım olacaq). Metodda getVolume()biz hesablamalar aparırıq - obyektimizin məlumatlarını həcmi göstərən rəqəmə çeviririk (uzunluğu, eni və hündürlüyünü çoxaldırıq). Bu, metodun nəticəsi olacaq rəqəmdir. Diqqət yetirin - metodun təsvirində yazılıb public int getVolume. Bu o deməkdir ki, bu metodun nəticəsi formada rəqəm olmalıdırint . Biz metodun nəticəsini hesabladıq və indi onu metodu çağıran proqramımıza qaytarmalıyıq . Java-da metodun nəticəsini qaytarmaq üçün açar sözdən istifadə olunur return.
return volume;

Metod parametrləri

Metodlar "metod parametrləri" adlanan dəyərləri giriş kimi qəbul edə bilər. getVolume()Sinifdəki mövcud metodumuz Truckheç bir parametr qəbul etmir, buna görə də nümunəni yük maşınları ilə genişləndirməyə çalışaq. Gəlin yeni bir sinif yaradaq - BridgeOfficer. Polis məmuru körpüdə növbətçilik edir və yoldan keçən bütün yük maşınlarının yüklərinin icazə verilən çəki həddini aşmamasını yoxlayır.
public class BridgeOfficer {

    int maxWeight;

    public BridgeOfficer(int normalWeight) {
        this.maxWeight = normalWeight;
    }

    public boolean checkTruck(Truck truck) {
        if (truck.weight > maxWeight) {
            return false;
        } else {
            return true;
        }
    }
}
Metod checkTruckgiriş kimi bir parametr götürür - yük maşını obyekti Truckvə məmurun yük maşınının körpüyə çıxmasına icazə verib-verməyəcəyini müəyyənləşdirir. Metodun içərisindəki məntiq olduqca sadədir: yük maşınının çəkisi icazə verilən maksimum həddən artıq olarsa, üsul geri qayıdır false. Başqa yol axtarmalı olacaqsınız :( Əgər çəki maksimumdan az və ya ona bərabərdirsə, keçə bilərsiniz və üsul geri qayıdır true. Əgər hələ də “qayıt”, “metod dəyər qaytarır” ifadələrini tam başa düşmürsən ” - gəlin proqramlaşdırmaya ara verək və real dünya həyatından sadə bir nümunə ilə buna baxaq :) Tutaq ki, siz xəstələndiniz və bir neçə gün işdə olmadınız. Siz ödəməli olduğunuz xəstəlik məzuniyyətinizlə mühasibatlığa gəlirsiniz. Metodlarla bənzətmə aparsaq, mühasibin bir üsulu var paySickLeave()(“xəstəlik məzuniyyəti”). Bu üsula bir parametr kimi xəstəlik məzuniyyəti şəhadətnaməsi keçirsiniz (onsuz üsul işləməyəcək və sizə heç bir şey ödənilməyəcək!). İş vərəqi metodunun içərisində lazımi hesablamalar aparılır (mühasib şirkətin sizə nə qədər ödəməli olduğunu hesablamaq üçün istifadə edir) və işin nəticəsi sizə qaytarılır - pul məbləği. Proqram eyni şəkildə işləyir. O, metodu çağırır, məlumatları oraya ötürür və nəhayət, nəticəni alır. main()Proqramımız üçün üsul budur BridgeOfficer:
public static void main(String[] args) {
    Truck first = new Truck();
    first.weight = 10000;
    Truck second = new Truck();
    second.weight = 20000;

    BridgeOfficer officer = new BridgeOfficer(15000);
    System.out.println("Truck number 1! May I pass, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck number 2! May I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
10.000 və 20.000 yüklü iki yük maşını yaradırıq.Eyni zamanda zabitin növbətçi olduğu körpünün maksimum çəkisi 15000-dir.Usul adlanan proqram officer.checkTruck(first), metod hər şeyi hesabladı və nəticəni proqrama qaytardı - true, və proqram onu ​​dəyişəndə ​​saxladı boolean canFirstTruckGo. İndi onunla istədiyini edə bilər (eynilə sizin mühasibdən aldığınız pulla). Sonda kod
boolean canFirstTruckGo = officer.checkTruck(first);
-a enir
boolean canFirstTruckGo = true;
Çox vacib bir məqam: operator returnyalnız metodun nəticəsini qaytarmır, həm də işini dayandırır ! Qaytarıldıqdan sonra yazılan bütün kodlar icra olunmayacaq!
public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, overweight!");
    } else {
        return true;
        System.out.println("Alright, move on!");
    }
}
Məmurun dediyi ifadələr konsola çıxmayacaq, çünki metod artıq nəticə verib və işini başa çatdırıb! Proqram metodun çağırıldığı nöqtəyə qayıtdı. Bu barədə özünüz narahat olmağa dəyməz - Java kompilyatoru -dən sonra kod yazmağa çalışsanız, xəta atmaq üçün kifayət qədər ağıllıdır return.

Avengers: Options War

Proqramımızın metodun necə işləməsi üçün bir neçə variant tələb etdiyi vəziyyətlər var. Niyə öz süni intellektimizi yaratmırıq? Amazonda Alexa var, Yandex-də Alice var, bəs biz niyə daha pisik? :) Dəmir adam haqqında filmdə Toni Stark özünün görkəmli süni intellektini yaradıb - JARVIS Gəlin gözəl personajı xatırlayaq və süni intellektimizi onun şərəfinə adlandıraq :) Jarvisə öyrətməli olduğumuz ilk şey - otağa girən insanlarla salamlaşmaq (belə bir böyük intellektin nəzakətsiz olduğu ortaya çıxsa, qəribə olardı).
public class Jarvis {

    public void sayHi(String name) {
        System.out.println("Good evening, " + name + ", How are you doing?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
    }
}
Konsol çıxışı:
Добрый вечер, Тони Старк, How ваши дела?
Əla! Jarvis içəri girən adamı necə qarşılamağı bilir. Çox vaxt, əlbəttə ki, onun sahibi olacaq - Tony Stark. Ancaq o, tək gəlməyə bilər! Bizim metodumuz sayHi()giriş kimi yalnız bir arqument alır. Və buna uyğun olaraq, gələnlərdən yalnız birinə salam verə biləcək, digərinə məhəl qoymayacaq. Çox nəzakətli deyilsiniz, razısınız? :/ Bu halda problemi həll etmək üçün sadəcə olaraq sinifdə eyni adlı, lakin fərqli parametrlərlə 2 metod yaza bilərik:
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ", How are you doing?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + ", " + secondGuest + ", How are you doing?");
    }
}
Buna metodun həddindən artıq yüklənməsi deyilir . Həddindən artıq yükləmə proqramımızın daha çevik olmasına və müxtəlif iş variantlarını yerləşdirməyə imkan verir. Bunun necə işlədiyini yoxlayaq:
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ", How are you doing?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + ", " + secondGuest + ", How are you doing?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
        jarvis.sayHi("Tony Stark", "Captain America");
    }
}
Konsol çıxışı:
Добрый вечер, Тони Старк, How ваши дела?
Добрый вечер, Тони Старк, Капитан Америка, How ваши дела?
Əla, hər iki variant işlədi :) Lakin, problemi həll etmədik! Üç qonaq olsa nə olar? sayHi()Əlbəttə ki, üç qonağın adını qəbul etmək üçün üsulu yenidən yükləyə bilərik . Ancaq bunlardan 4 və ya 5 ola bilər.Və s sonsuza qədər. Jarvisə milyonlarla metod yüklənmədən istənilən sayda adla işləməyi öyrətməyin başqa yolu varmı sayHi()? :/ Əlbəttə var! Əks halda Java dünyanın ən populyar proqramlaşdırma dili olardımı? ;)
public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ", How are you doing?");
    }
}
Parametr kimi ötürülən qeyd ( String...names) bizə müəyyən sayda sətirlərin metoda ötürüldüyünü bildirməyə imkan verir. Nə qədər olacağını əvvəlcədən dəqiqləşdirmirik, buna görə də metodumuzun işi indi daha çevik olur:
public class Jarvis {

    public void sayHi(String...names) {
        for (String name: names) {
            System.out.println("Good evening, " + name + ", How are you doing?");
        }
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
    }
}
Konsol çıxışı:
Добрый вечер, Тони Старк, How ваши дела?
Добрый вечер, Капитан Америка, How ваши дела?
Добрый вечер, Черная Вдова, How ваши дела?
Добрый вечер, Халк, How ваши дела?
Buradakı kodlardan bəziləri sizə tanış deyil, lakin buna fikir verməyin. Onun mahiyyəti sadədir - üsul öz növbəsində bütün adlardan keçir və qonaqların hər birini salamlayır! Üstəlik, istənilən sayda köçürülmüş xətlər üçün işləyəcək! İki, on, hətta min - üsul istənilən sayda qonaqla etibarlı şəkildə işləyəcək. Bütün mümkün variantlar üçün həddən artıq yükləmələr etməkdən daha rahatdır, razı deyilsiniz? :) Başqa bir vacib məqam: arqumentlərin sırası vacibdir! Deyək ki, metodumuz giriş kimi bir sətir və bir ədəd götürür:
public class Man {

    public static void sayYourAge(String greeting, int age) {
        System.out.println(greeting + " " + age);
    }

    public static void main(String[] args) {
        sayYourAge("My age - ", 33);
        sayYourAge(33, "My age - "); //error!
    }
}
sayYourAgeSinif metodu giriş kimi sətir və rəqəm götürürsə Man, proqramda onların ötürülməsi lazım olan ardıcıllıq budur! Onları fərqli ardıcıllıqla keçirsək, tərtibçi xəta atacaq və adam öz yaşını deyə bilməyəcək. Yeri gəlmişkən, sonuncu mühazirədə bəhs etdiyimiz konstruktorlar da üsullardır! Onlar həmçinin həddən artıq yüklənə bilər (müxtəlif arqumentlər dəsti ilə bir neçə konstruktor yarada) və onlar üçün arqumentlərin ötürülməsi sırası da əsaslı əhəmiyyət kəsb edir. Həqiqi üsullar! :)

Və yenə parametrlər haqqında

Hə, bəli, onlarla hələ bitməmişik :) İndi nəzərdən keçirəcəyimiz mövzu çox önəmlidir. Bütün gələcək müsahibələrinizdə bu barədə soruşacaqları ehtimalı 90% var! Parametrlərin metodlara ötürülməsi haqqında danışacağıq. Sadə bir misala baxaq:
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        currentYear = currentYear-10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2020;

        System.out.println("What is the year now?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And now?");
        System.out.println(currentYear);
    }
}
Zaman maşınının iki üsulu var. Hər ikisi cari ili təmsil edən rəqəmi giriş kimi qəbul edir və dəyəri artırır və ya azaldır (vaxtda və ya gələcəyə qayıtmaq istəməyimizdən asılı olaraq). Ancaq konsol çıxışından göründüyü kimi, üsul işləmədi! Konsol çıxışı:
Какой сейчас год?
2020
А сейчас?
2020
currentYearDəyişən metoda keçdik goToPast(), lakin onun dəyəri dəyişmədi. 2020-ci ildə necə idisə, elə də qalır. Bəs niyə? :/ Çünki Java-da primitivlər dəyərə görə metodlara ötürülür. Bunun mənası nədi? Biz metodu çağırıb goToPast()dəyişənimizi ora ötürdükdə int currentYear = 2020metoda dəyişənin özü deyil currentYear, onun surəti daxil olur . Bu nüsxənin dəyəri, əlbəttə ki, 2020-yə bərabərdir, lakin nüsxədə baş verən bütün dəyişikliklər heç bir şəkildə orijinal dəyişənimizə təsir göstərmircurrentYear ! Gəlin kodumuzu daha ətraflı edək və ilə nə baş verdiyini görək currentYear:
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        System.out.println("The goToPast method has started!");
        System.out.println("The currentYear value inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("The currentYear value inside the goToPast method (at the end) = " + currentYear);
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2020;

        System.out.println("What is the year at the very beginning of the program?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("What year is it now?");
        System.out.println(currentYear);
    }
}
Konsol çıxışı:
Какой год в самом начале работы программы?
2020
Метод goToPast начал работу!
Значение currentYear внутри метода goToPast (в начале) = 2020
Значение currentYear внутри метода goToPast (в конце) = 2010
А сейчас Howой год?
2020
Bu açıq şəkildə göstərir ki, metoda ötürülən dəyişən goToPast()yalnız bir nüsxədir currentYear. Və surətin dəyişdirilməsi “orijinal”ın mənasına heç bir təsir göstərmədi. " İstinadla keçmək " tam əks məna daşıyır. Gəlin pişiklər üzərində məşq edək! Demək istədiyim odur ki, görək keçiddən keçmək pişiklərdən nümunə götürməklə necə görünür :)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
İndi zaman maşınımızın köməyi ilə biz keçmişə və gələcəyə dünyanın ilk pişik vaxtı səyahətçisi olan Barsik-i işə salacağıq! TimeMachineMaşının obyektlərlə işləyə bilməsi üçün sinfi dəyişdirək Cat;
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
Metodlar indi yalnız ötürülən nömrəni deyil, agekonkret obyektin sahəsini də dəyişir Cat. Primitivlər vəziyyətində, xatırladığınız kimi, uğur qazana bilmədik: orijinal nömrə dəyişmədi. Gəlin görək burada nə baş verir!
public static void main(String[] args) {

    TimeMachine timeMachine = new TimeMachine();
    Cat barsik = new Cat(5);

    System.out.println("How old is Barsik at the very beginning of the program?");
    System.out.println(barsik.age);

    timeMachine.goToFuture(barsik);
    System.out.println("And now?");
    System.out.println(barsik.age);

    System.out.println("Firs-sticks! Barsik has aged 10 years! Drive back quickly!");
    timeMachine.goToPast(barsik);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(barsik.age);
}
Konsol çıxışı:
Сколько лет Барсику в самом начале работы программы?
5
А теперь?
15
Елки-палки! Барсик постарел на 10 лет! Живо гони назад!
Получилось? Мы вернули коту его изначальный возраст?
5
Heyrət! Vay! İndi üsul fərqli işləyirdi: pişikimiz birdən qocaldı və sonra yenidən gənc göründü! :) Gəlin bunun səbəbini anlamağa çalışaq. Primitivlərlə nümunədən fərqli olaraq, obyektlər vəziyyətində obyektə istinad metoda ötürülür. Orijinal obyektimizə istinad üsullara goToFuture(barsik)keçdi . Buna görə də, daxili metodları dəyişdirdikdə , obyektimizin saxlandığı yaddaş sahəsinə daxil oluruq. Bu, başlanğıcda yaratdığımız eyni Barsik ilə əlaqədir. Buna "istinadla keçmək" deyilir! Ancaq bu bağlantılarla hər şey o qədər də sadə deyil :) Gəlin nümunəmizi dəyişdirməyə çalışaq: goToPast(barsik)barsikbarsik.age
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat = new Cat(cat.age);
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat = new Cat(cat.age);
        cat.age -= 10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        Cat barsik = new Cat(5);

        System.out.println("How old is Barsik at the very beginning of the program?");
        System.out.println(barsik.age);

        timeMachine.goToFuture(barsik);
        System.out.println("Barsik went to the future! Has his age changed?");
        System.out.println(barsik.age);

        System.out.println("And if you try in the past?");
        timeMachine.goToPast(barsik);
        System.out.println(barsik.age);
    }
}
Konsol çıxışı:
Сколько лет Барсику в самом начале работы программы?
5
Барсик отправился в будущее! Его возраст изменился?
5
А если попробовать в прошлое?
5
Yenidən işləmir! O_O Gəlin nə baş verdiyini anlayaq :) Bütün bunlar linklərin necə işləməsinin üsulları goToPast/ goToFuturevə mexanikasıdır. İndi diqqət!Bu nöqtə bağlantıların və metodların necə işlədiyini başa düşmək üçün ən vacibdir . Əslində, metodu çağırdığımız zaman goToFuture(Cat cat)ona ötürülən obyekt istinadının özü deyil cat, bu istinadın surətidir. Yəni bir obyekti metoda ötürəndə bu obyektə iki istinad olur . Bu, baş verənləri başa düşmək üçün çox vacibdir. Axı, buna görə də son nümunəmiz pişiyin yaşını dəyişmədi. Yaşın dəyişdirilməsi ilə əvvəlki nümunədə biz sadəcə olaraq metodun içindən keçən istinadı götürdük goToFuture(), ondan istifadə edərək yaddaşdakı obyekti tapdıq və yaşını dəyişdirdik ( cat.age += 10). İndi metodun içərisində goToFuture()yeni bir obyekt yaradırıq
(cat = new Cat(cat.age)),
və metoda ötürülən eyni nüsxə linki bu obyektə təyin edilir. Nəticə olaraq:
  • Birinci keçid ( Cat barsik = new Cat(5)) orijinal pişiyi göstərir (5 yaşında)
  • catDəyişəni metoda ötürdükdən goToPast(Cat cat)və onu yeni obyektə təyin etdikdən sonra istinad kopyalandı.
Bundan sonra son vəziyyətimiz var: iki keçid iki fərqli obyektə işarə edir. Ancaq onlardan yalnız birinin yaşını dəyişdirdik - metodun içərisində yaratdığımız.
cat.age += 10;
main()Və təbii olaraq, metodda onu konsola çıxardıqda barsik.age, yaşının dəyişmədiyini görürük. Axı barsikbu, hələ də heç nə baş vermədiyi 5 yaşında köhnə, orijinal obyektə işarə edən istinad dəyişənidir. Yaşla bütün manipulyasiyalarımız yeni bir obyektdə edildi. Beləliklə, məlum olur ki, obyektlər metodlara istinadla ötürülür. Obyektlərin surətləri heç vaxt avtomatik olaraq yaradılmır. Bir pişik obyektini metoda ötürsəniz və onun yaşını dəyişdirsəniz, o, uğurla dəyişəcək. Lakin istinad dəyişənlərinin dəyərləri metodları təyin edərkən və/və ya çağırarkən kopyalanır ! Primitivlərin ötürülməsi ilə bağlı bəndi burada təkrarlayaq: “Biz metodu çağırıb changeInt()dəyişənimizi ora ötürəndə int x = 15metoda dəyişənin özü deyil x, onun surəti daxil olur.Axı surətdə baş verən bütün dəyişikliklər heç bir dəyişikliyə səbəb olmur. orijinal dəyişənimizə hər hansı şəkildə təsir edir x. Kopyalama keçidləri ilə hər şey eyni işləyir! Siz pişik obyektini metoda keçirsiniz. Əgər pişiyin özü ilə (yəni yaddaşda olan obyektlə) bir şey etsəniz, bütün dəyişikliklər uğurla keçəcək - bizdə yalnız bir obyekt var idi və hələ də var. Amma metod daxilində yeni obyekt yaradıb onu metodun parametri olan istinad dəyişənində saxlayırsınızsa, bundan sonra bizdə iki obyekt və iki istinad dəyişəni var. Hamısı budur! O qədər də asan deyildi, hətta bir neçə dəfə mühazirə oxumalı ola bilərsən. Amma əsas odur ki, siz bu super vacib mövzunu öyrənmisiniz. Java-da arqumentlərin necə ötürülməsi ilə bağlı tez-tez mübahisələrlə (hətta təcrübəli tərtibatçılar arasında da) qarşılaşacaqsınız. İndi bunun necə işlədiyini dəqiq bilirsiniz. Davam et! :)
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION