JavaRush /Java блогы /Random-KK /Әдістер, олардың параметрлері, өзара әрекеттесу және шама...

Әдістер, олардың параметрлері, өзара әрекеттесу және шамадан тыс жүктеу

Топта жарияланған
Тағы да сәлем! Соңғы дәрісте біз сыныптармен және конструкторлармен танысып, өзімізді құруды үйрендік. Әдістер, олардың параметрлері, өзара әрекеттесу және шамадан тыс жүктеу – 1Бүгін біз әдістер сияқты сабақтардың құрамдас бөлігін егжей-тегжейлі қарастырамыз. Әдіс – программадағы кейбір операцияларды орындауға мүмкіндік беретін командалар жиынтығы. Басқаша айтқанда, әдіс - бұл функция; сіздің сынып жасай алатын нәрсе. Басқа бағдарламалау тілдерінде әдістерді көбінесе «функциялар» деп атайды, бірақ Java тілінде «әдіс» сөзі танымал бола бастады :) Өткен дәрісте, есіңізде болса, мысықтарымыз мияулай алатындай етіп Cat сыныбына қарапайым әдістерді жасаған болатынбыз. және секіру:
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()біздің сыныптың әдістері болып табылады. Олардың жұмысының нәтижесі консольге шығу болып табылады:
Мяу!
Прыг-скок!
Біздің әдістеріміз өте қарапайым: олар мәтінді консольге басып шығарады. Бірақ Java-да әдістердің негізгі міндеті бар - олар an objectінің деректерінде әрекеттерді орындауы керек . Нысан деректерінің мәнін өзгертіңіз, түрлендіріңіз, консольге шығарыңыз немесе онымен басқа әрекет жасаңыз. Біздің қазіргі әдістеріміз нысан деректерімен ештеңе жасамайды Cat. Нақтырақ мысалды қарастырайық:
public class Truck {

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

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
Мысалы, бізде жүк көлігін білдіретін класс бар - Truck. Жүк көлігі тіркемесінің ұзындығы, ені және биіктігі және салмағы бар (бұл кейінірек қажет болады). Әдісте getVolume()біз есептеулерді орындаймыз - an objectіміздің деректерін көлемді көрсететін санға түрлендіреміз (ұзындығын, енін және биіктігін көбейтеміз). Бұл әдістің нәтижесі болатын сан. Назар аударыңыз - бұл әдіс сипаттамасында жазылған public int getVolume. Бұл әдістің нәтижесі формадағы сан болуы керекint дегенді білдіреді . Біз әдістің нәтижесін есептедік, енді оны әдіс деп атаған бағдарламамызға қайтаруымыз керек. Java тіліндегі әдістің нәтижесін қайтару үшін кілт сөзі пайдаланылады return.
return volume;

Әдіс параметрлері

Әдістер мәндерді енгізу ретінде қабылдай алады, олар «әдіс параметрлері» деп аталады. Біздің getVolume()сыныптағы қазіргі әдісіміз Truckешқандай параметрлерді қабылдамайды, сондықтан мысалды жүк көліктерімен кеңейтуге тырысайық. Жаңа класс құрайық - BridgeOfficer. Полиция қызметкері көпірде кезекшілік етеді және барлық өтіп бара жатқан жүк көліктерін тексеріп, олардың жүктерінің рұқсат етілген салмақ шегінен асып кетпеуін тексереді.
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;
        }
    }
}
Әдіс checkTruckкіріс ретінде бір параметрді - жүк көлігі an objectісін қабылдайды Truckжәне офицер жүк көлігін көпірге шығара ма, жоқ па, соны анықтайды. Әдістің ішіндегі логика өте қарапайым: жүк көлігінің салмағы рұқсат етілген ең жоғарыдан асып кетсе, әдіс қайтарылады false. Басқа жолды іздеуге тура келеді :( Салмақ максимумнан аз немесе оған тең болса, өтуге болады және әдіс қайтарылады. trueЕгер сіз әлі де «қайтару», «әдіс мәнді қайтарады. ” - бағдарламалаудан үзіліс жасап, шынайы өмірден қарапайым мысалды қолданып көрейік :) Сіз ауырып қалдыңыз және бірнеше күн жұмыста болмадыңыз делік. Бухгалтерияға еңбекке жарамсыздық парағымен келесіз, оны төлеу керек. Егер әдістерге ұқсастық жасасақ, онда бухгалтердің әдісі бар paySickLeave()(«ауру демалысын төлеу»). Сіз бұл әдіске параметр ретінде науқастық парақ туралы анықтаманы бересіз (онсыз әдіс жұмыс істемейді және сізге ештеңе төленбейді!). Жұмыс парағы әдісінің ішінде қажетті есептеулер жүргізіледі (бухгалтер оны компания сізге қанша төлеуі керек екенін есептеу үшін пайдаланады) және жұмыс нәтижесі сізге қайтарылады - ақша сомасы. Бағдарлама дәл осылай жұмыс істейді. Ол әдісті шақырады, деректерді сол жерге жібереді және соңында нәтижені алады. main()Міне, біздің бағдарламамыздың әдісі 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 және 20 000 жүктері бар екі жүк көлігін жасап жатырмыз. Бұл ретте офицер кезекшілік ететін көпірдің максималды салмағы 15 000. Әдіс деп аталатын бағдарлама officer.checkTruck(first), әдіс бәрін есептеп, нәтижені бағдарламаға қайтарды - true, және бағдарлама оны айнымалыда сақтады boolean canFirstTruckGo. Енді ол онымен қалағанын жасай алады (дәл сіз бухгалтерден алған ақшаңыз сияқты). Ақыр соңында code
boolean canFirstTruckGo = officer.checkTruck(first);
дейін түседі
boolean canFirstTruckGo = true;
Өте маңызды сәт: оператор returnәдістің нәтижесін қайтарып қана қоймай, оның жұмысын тоқтатады ! Қайтарылғаннан кейін жазылған барлық code орындалмайды!
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!");
    }
}
Офицер айтқан сөйлемдер консольге шығарылмайды, өйткені әдіс нәтиже беріп, жұмысын аяқтады! Бағдарлама әдіс шақырылған нүктеге оралды. Бұл туралы өзіңіз уайымдаудың қажеті жоқ - Java компиляторы -дан кейін code жазуға тырыссаңыз, қате жіберуге жеткілікті ақылды return.

Кек алушылар: Соғыс опциялары

Біздің бағдарлама әдіс қалай жұмыс істейтіні үшін бірнеше опцияны талап ететін жағдайлар бар. Неге біз өз жасанды интеллектімізді жасамаймыз? Amazon-да Alexa бар, Яндекс-те Алиса бар, сондықтан біз неге нашар? :) Темір адам туралы фильмде Тони Старк өзінің көрнекті жасанды интеллектін жасады - ДЖАРВИС Керемет кейіпкерге құрмет көрсетіп, оның құрметіне AI-ды атайық :) Біріншіден, біз Джарвиске үйретуіміз керек - бөлмеге кірген адамдармен сәлемдесу (осындай ұлы интеллект әдепсіз болып шықса, біртүрлі болар еді).
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");
    }
}
Консоль шығысы:
Добрый вечер, Тони Старк, How ваши дела?
Тамаша! Жарвис ішке кірген адаммен қалай амандасуды біледі. Көбінесе, әрине, бұл оның иесі болады - Тони Старк. Бірақ ол жалғыз келмеуі мүмкін! Ал біздің әдіс sayHi()кіріс ретінде бір ғана аргументті қабылдайды. Ал, сәйкесінше, келгендердің біреуіне ғана сәлем беріп, екіншісін елемейді. Өте сыпайы емес, келісесіз бе? :/ Бұл жағдайда есепті шешу үшін класста аты бірдей, бірақ параметрлері әртүрлі 2 әдісті жазуға болады:
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 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");
    }
}
Консоль шығысы:
Добрый вечер, Тони Старк, How ваши дела?
Добрый вечер, Тони Старк, Капитан Америка, How ваши дела?
Тамаша, екі нұсқа да жұмыс істеді :) Дегенмен, біз мәселені шешпедік! Үш қонақ болса ше? Әрине, біз sayHi()үш қонақтың атын қабылдау үшін әдісті қайта жүктей аламыз. Бірақ олардың 4 немесе 5 болуы мүмкін және т.б. ad infinitum. Джарвиске миллиондаған әдісті шамадан тыс жүктемесіз кез келген атаулармен жұмыс істеуге үйретудің басқа жолы бар ма sayHi()? :/ Әрине бар! Әйтпесе, Java әлемдегі ең танымал бағдарламалау тілі болар ма еді? ;)
public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ", How are you doing?");
    }
}
Параметр ретінде берілген жазба ( String...names) жолдардың белгілі бір саны әдіске жіберілгенін көрсетуге мүмкіндік береді. Біз олардың қанша болуы керектігін алдын ала көрсетпейміз, сондықтан біздің әдістің жұмысы енді әлдеқайда икемді болады:
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");
    }
}
Консоль шығысы:
Добрый вечер, Тони Старк, How ваши дела?
Добрый вечер, Капитан Америка, How ваши дела?
Добрый вечер, Черная Вдова, How ваши дела?
Добрый вечер, Халк, How ваши дела?
Мұнда кейбір codeтар сізге таныс емес, бірақ бұған қарсы болмаңыз. Оның мәні қарапайым - әдіс кезегімен барлық атаулардан өтіп, қонақтардың әрқайсысын қарсы алады! Сонымен қатар, ол кез келген тасымалданатын желілер үшін жұмыс істейді! Екі, он, тіпті мың - әдіс қонақтардың кез келген санымен сенімді жұмыс істейді. Барлық мүмкін нұсқалар үшін шамадан тыс жүктеме жасаудан әлдеқайда ыңғайлы, келісесіз бе? :) Тағы бір маңызды мәселе: дәлелдердің реті маңызды! Біздің әдіс кіріс ретінде жолды және санды алады делік:
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!
    }
}
sayYourAgeКласс әдісі кіріс ретінде жолды және санды қабылдаса Man, онда бұл оларды бағдарламада беру керек реттілік! Егер біз оларды басқа ретпен өткізсек, компилятор қате жібереді және адам өзінің жасын айта алмайды. Айтпақшы, біз өткен дәрісте қарастырған конструкторлар да әдістер! Олар сондай-ақ шамадан тыс жүктелуі мүмкін (әр түрлі аргументтер жиыны бар бірнеше конструкторларды жасаңыз) және олар үшін дәлелдерді беру тәртібі де принципті түрде маңызды. Нақты әдістер! :)

Және тағы да параметрлер туралы

Иә, иә, біз олармен әлі біткен жоқпыз :) Қазір қарастыратын тақырып өте маңызды. Сіздің болашақ сұхбаттарыңызда олар бұл туралы сұрайтынына 90% мүмкіндік бар! Параметрлерді әдістерге беру туралы айтатын боламыз. Қарапайым мысалды қарастырайық:
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);
    }
}
Уақыт машинасының екі әдісі бар. Екеуі де кіріс ретінде ағымдағы жылды білдіретін санды қабылдайды және мәнді арттырады немесе азайтады (уақытқа немесе болашаққа оралғымыз келетініне байланысты). Бірақ, консоль шығысынан көрініп тұрғандай, әдіс жұмыс істемеді! Консоль шығысы:
Какой сейчас год?
2020
А сейчас?
2020
currentYearБіз әдіске айнымалыны бердік goToPast(), бірақ оның мәні өзгермеді. 2020 жылы қандай болса, солай болып қалды. Бірақ неге? :/ Өйткені Java тіліндегі примитивтер мәндер бойынша әдістерге беріледі. Бұл нені білдіреді? Әдісті шақырып goToPast(), айнымалыны сол жерге бергенде int currentYear = 2020, әдіске айнымалының өзі емес currentYear, оның көшірмесі түседі . Бұл көшірменің мәні, әрине, 2020-ға тең, бірақ көшірмеде болатын барлық өзгерістер біздің бастапқы айнымалыға ешқандай әсер етпейдіcurrentYear ! Кодымызды егжей-тегжейлі етіп, не болатынын көрейік 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);
    }
}
Консоль шығысы:
Какой год в самом начале работы программы?
2020
Метод goToPast начал работу!
Значение currentYear внутри метода goToPast (в начале) = 2020
Значение currentYear внутри метода goToPast (в конце) = 2010
А сейчас Howой год?
2020
Бұл әдіске берілген айнымалы goToPast()тек көшірме екенін анық көрсетеді currentYear. Ал көшірмені өзгерту «түпнұсқаның» мағынасына әсер еткен жоқ. « Анықтама бойынша өту » мүлдем қарама-қарсы мағынаға ие. Мысықтарға жаттығу жасайық! Айтайын дегенім, мысал ретінде мысықтарды пайдалану арқылы сілтеме арқылы өту қандай болатынын көрейік :)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Енді уақыт машинасының көмегімен біз әлемдегі алғашқы мысық уақыт саяхатшысы Барсикті өткенге және болашаққа шығарамыз! TimeMachineМашина an objectілермен жұмыс істей алатындай сыныпты өзгертейік Cat;
public class TimeMachine {

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

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
ageӘдістер енді берілген санды ғана емес, белгілі бір нысанның өрісін де өзгертеді Cat. Примитивтер жағдайында, есіңізде болса, біз сәтті болмадық: бастапқы сан өзгермеді. Мұнда не болатынын көрейік!
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);
}
Консоль шығысы:
Сколько лет Барсику в самом начале работы программы?
5
А теперь?
15
Елки-палки! Барсик постарел на 10 лет! Живо гони назад!
Получилось? Мы вернули коту его изначальный возраст?
5
Апыр-ай! Енді әдіс басқаша жұмыс істеді: біздің мысық кенеттен қартаяды, содан кейін қайтадан жас көрінді! :) Неге екенін анықтауға тырысайық. Примитивтері бар мысалдан айырмашылығы, an objectілер жағдайында нысанға сілтеме әдіске беріледі. Біздің бастапқы нысанымызға сілтеме әдістерге goToFuture(barsik)берілді . Сондықтан, біз ішкі әдістерді өзгерткенде , an objectіміз сақталған жад аймағына қол жеткіземіз. Бұл біз ең басында жасаған Барсикке сілтеме. Бұл «анықтама бойынша өту» деп аталады! Дегенмен, бұл сілтемелермен бәрі оңай емес :) Біздің мысалды өзгертуге тырысайық: 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);
    }
}
Консоль шығысы:
Сколько лет Барсику в самом начале работы программы?
5
Барсик отправился в будущее! Его возраст изменился?
5
А если попробовать в прошлое?
5
Қайтадан жұмыс істемейді! O_O Не болғанын анықтайық :) Мұның бәрі сілтемелердің қалай жұмыс істейтінінің әдістері goToPast/ goToFutureжәне механикасы туралы. Енді назар аударыңыз!Бұл нүкте сілтемелер мен әдістердің қалай жұмыс істейтінін түсіну үшін ең маңызды болып табылады. Шындығында, әдісті шақырған кезде goToFuture(Cat cat)оған нысан сілтемесінің өзі емес cat, осы сілтеменің көшірмесі беріледі. Яғни, нысанды әдіске бергенде, осы нысанға екі сілтеме бар . Бұл не болып жатқанын түсіну үшін өте маңызды. Өйткені, біздің соңғы мысал мысықтың жасын өзгертпеді. Алдыңғы мысалда жасты өзгерту арқылы біз жай ғана әдіс ішінде берілген сілтемені алдық goToFuture(), оның көмегімен жадтағы an objectіні тауып, оның жасын өзгерттік ( cat.age += 10). Енді әдіс ішінде goToFuture()біз жаңа нысан жасаймыз
(cat = new Cat(cat.age)),
және әдіске жіберілген бірдей көшірме сілтемесі осы нысанға тағайындалады. Нәтижесінде:
  • Бірінші сілтеме ( Cat barsik = new Cat(5)) бастапқы мысықты көрсетеді (5 жаста)
  • Біз айнымалыны catәдіске беріп goToPast(Cat cat), оны жаңа нысанға тағайындағаннан кейін сілтеме көшірілді.
Осыдан кейін бізде соңғы жағдай бар: екі сілтеме екі түрлі нысанды көрсетеді. Бірақ біз олардың тек біреуінің жасын өзгерттік - әдістің ішінде жасаған жасын.
cat.age += 10;
Әрине, біз оны main()консольге әдісте шығарған кезде barsik.age, оның жасы өзгермегенін көреміз. Өйткені barsik, бұл 5 жастағы ескі, бастапқы нысанды көрсететін анықтамалық айнымалы, оған ештеңе болмаған. Жасы бойынша біздің барлық манипуляцияларымыз жаңа нысанда жасалды. Осылайша, нысандар сілтеме арқылы әдістерге беріледі. Нысандардың көшірмелері ешқашан автоматты түрде жасалмайды. Егер сіз мысық нысанын әдіске өткізіп, оның жасын өзгертсеңіз, ол сәтті өзгереді. Бірақ анықтамалық айнымалылардың мәндері әдістерді тағайындау және/немесе шақыру кезінде көшіріледі! Мұнда примитивтерді беру туралы абзацты қайталайық: «Біз әдісті шақырып changeInt(), айнымалыны сол жерге бергенде int x = 15, әдіске айнымалының өзі емес x, оның көшірмесі түседі .. Өйткені көшірмеде болатын өзгерістердің бәрі өзгермейді. біздің бастапқы айнымалыға кез келген жолмен әсер етеді x». Сілтемелерді көшіру арқылы бәрі бірдей жұмыс істейді! Сіз әдіске мысық нысанын бересіз. Егер сіз мысықтың өзімен (яғни жадтағы an objectімен) бірдеңе жасасаңыз, барлық өзгерістер сәтті өтеді - бізде бір ғана нысан болды және ол әлі де бар. Бірақ әдіс ішінде сіз жаңа нысан жасап, оны әдістің параметрі болып табылатын анықтамалық айнымалыға сақтасаңыз, бұдан былай бізде екі нысан және екі анықтамалық айнымалы болады. Осымен болды! Бұл оңай болған жоқ, тіпті бірнеше рет лекция оқуға тура келуі мүмкін. Ең бастысы, сіз бұл өте маңызды тақырыпты білдіңіз. Сіз Java-да аргументтердің қалай берілетіні туралы аргументтерді жиі кездестіресіз (тіпті тәжірибелі әзірлеушілер арасында да). Енді сіз оның қалай жұмыс істейтінін нақты білесіз. Бәрекелді! :)
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION