CodeGym/Java Blogu/Rastgele/Java'daki Yöntemler
John Squirrels
Seviye
San Francisco

Java'daki Yöntemler

grupta yayınlandı
Tekrar merhaba! Son derste sınıflar ve oluşturucularla tanıştık ve kendimizinkini nasıl oluşturacağımızı öğrendik. Bugün derslerin olmazsa olmazı Java Metotlarını daha yakından tanıyacağız. Java'daki Yöntemler, bir programda belirli bir işlemi gerçekleştirmenize izin veren bir dizi komuttur. Başka bir deyişle, bir yöntem bir işlevdir; sınıfınızın yapabileceği bir şey. Diğer programlama dillerinde, yöntemler genellikle "işlevler" olarak adlandırılır, ancak Java'da "yöntem" kelimesi daha yaygındır. :) Hatırlarsanız geçen derste bir Cat sınıfı için basit yöntemler geliştirmiştik, kedilerimiz miyavlasın, zıplasın diye:
public class Cat {

    String name;
    int age;

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

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

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

        smudge.sayMeow();
        smudge.jump();
    }
}
sayMeow() ve jump() sınıfımızın metotlarıdır. Ve bu yöntemleri çalıştırmak, aşağıdaki konsol çıktısıyla sonuçlanır:
Meow!
Pounce!
Yöntemlerimiz oldukça basit: sadece konsola metin çıktısı veriyorlar. Ancak Java'da yöntemlerin önemli bir görevi vardır: bir nesnenin verileri üzerinde eylemler gerçekleştirirler. Nesnenin verilerini değiştirir, dönüştürür, görüntüler ve onunla başka şeyler yaparlar. Mevcut yöntemlerimiz, Cat nesnesinin verileriyle hiçbir şey yapmaz . Daha açıklayıcı bir örneğe bakalım:
public class Truck {

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

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
Örneğin, burada bir Truck'ı temsil eden bir sınıfımız var . Yarı kamyonun uzunluğu, genişliği, yüksekliği ve ağırlığı vardır (bunlara daha sonra ihtiyacımız olacak). getVolume() yönteminde , nesnemizin verilerini hacmini temsil eden bir sayıya dönüştürerek hesaplamalar yaparız (uzunluk, genişlik ve yüksekliği çarparız). Bu sayı yöntemin sonucu olacaktır. Yöntem bildiriminin public int getVolume olarak yazıldığına dikkat edin . Bu, bu yöntemin bir int döndürmesi gerektiği anlamına gelir . Metodun dönüş değerini hesapladık ve şimdi onu metodumuzu çağıran programa geri döndürmeliyiz. Java'da bir yöntemin sonucunu döndürmek için, dönüş anahtar kelimesini kullanırız. dönüş hacmi;

Java Yöntemi Parametreleri

Bir metodu çağırırken ona "arguments" denilen değerleri iletebiliriz. Bir yöntemin bildirimi, yöntemin kabul edebileceği değişkenlerin türünü ve sırasını bize söyleyen değişkenlerin bir listesini içerir. Bu listeye "yöntem parametreleri" denir. Kamyon sınıfımızın getVolume() yöntemi şu anda herhangi bir parametre tanımlamıyor, bu nedenle kamyon örneğimizi genişletmeyi deneyelim . BridgeOfficer adlı yeni bir sınıf oluşturun . Bu, bir köprüde görev yapan ve geçen tüm kamyonları yüklerinin izin verilen ağırlığı aşıp aşmadığını kontrol eden bir polis memuru.
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 yöntemi bir bağımsız değişkeni, bir Truck nesnesini kabul eder ve memurun kamyonun köprüde olmasına izin verip vermeyeceğini belirler . Yöntemin içindeki mantık yeterince basittir: kamyonun ağırlığı izin verilen maksimum değeri aşarsa, yöntem false değerini döndürür . Başka bir yol bulması gerekecek :( Ağırlık maksimuma eşit veya ondan küçükse geçebilir ve yöntem true değerini döndürür. "dönüş" veya "yöntem bir değer döndürür" ifadelerini henüz tam olarak anlamadıysanız, programlamaya ara verelim ve gerçek hayattan basit bir örnek kullanarak bunları ele alalım. :) Diyelim ki hastalandınız ve birkaç gün işten çıkıp evde kaldınız. Hastalık izninin ödenmesi gerektiği için doktor raporu ile muhasebeye gidiyorsunuz. Bu durumu metotlarla karşılaştırırsak, muhasebecinin bir paySickLeave() işlevi vardır.yöntem. Bu yönteme argüman olarak bir doktor notu iletirsiniz (onsuz, yöntem çalışmaz ve size ödeme yapılmaz!). Daha sonra notunuz kullanılarak yöntem içerisinde gerekli hesaplamalar yapılır (muhasebeci bunu şirketin size ne kadar ödemesi gerektiğini hesaplamak için kullanır) ve çalışmanızın sonucu (bir miktar para) size iade edilir. Programımız benzer şekilde çalışmaktadır. Bir yöntemi çağırır, ona veri iletir ve sonunda bir sonuç alır. İşte BridgeOfficer programımızın main() yöntemi:
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 1! Can I go, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck 2! And can I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
10.000 ve 20.000'lik iki kamyon yaratıyoruz. Ve memurun çalıştığı köprünün maksimum ağırlığı 15.000. Program, official.checkTruck(ilk) yöntemini çağırır. Yöntem her şeyi hesaplar ve ardından programın canFirstTruckGo boolean değişkenine kaydettiği true değerini döndürür . Artık onunla ne istersen yapabilirsin (tıpkı muhasebecinin sana verdiği parayla yaptığın gibi). Günün sonunda, kod
boolean canFirstTruckGo = officer.checkTruck(first);
indirgenir
boolean canFirstTruckGo =  true;
İşte çok önemli bir nokta: return ifadesi sadece yöntemin dönüş değerini döndürmez, aynı zamanda yöntemin çalışmasını da durdurur! return deyiminden sonra gelen kodlar çalıştırılmayacaktır!
public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, you're overweight!");
    } else {
        return true;
        System.out.println("Everything looks good, go ahead!");
    }
}
Yöntem zaten bir sonuç döndürdüğü ve sonlandırıldığı için memurun yorumları görüntülenmeyecek! Program, yöntemin çağrıldığı yere geri döner. Bunu izlemek zorunda değilsiniz: Java derleyicisi, bir dönüş ifadesinden sonra kod yazmaya çalıştığınızda hata üretecek kadar akıllıdır .

Yenilmezler: Parametre Savaşı

Bir yöntemi çağırmak için birkaç yol isteyeceğimiz durumlar vardır. Neden kendi yapay zekamızı yaratmayalım? Amazon'da Alexa var, Apple'da Siri var, öyleyse neden bizde olmasın? :) Demir Adam filminde Tony Stark kendi inanılmaz yapay zekası Jarvis'i yaratıyor. Bu harika karaktere saygılarımızı sunalım ve yapay zekamıza onun adını verelim. :) Yapmamız gereken ilk şey, Jarvis'e odaya giren insanlara merhaba demeyi öğretmek (böylesine harika bir zekanın kaba çıkması tuhaf olurdu).
public class Jarvis {

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

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
    }
}
Konsol çıktısı:
Good evening, Tony Stark. How are you?
Çok güzel! Jarvis artık konukları ağırlayabilir. Tabii ki, çoğu zaman ustası Tony Stark olacaktır. Ama ya yalnız gelmezse! sayHi() yöntemimiz yalnızca bir bağımsız değişkeni kabul eder. Ve böylece odaya giren sadece bir kişiyi selamlayabilir ve diğerini görmezden gelir. Pek kibar değil, aynı fikirde değil misin? :/

Java Yöntemi Aşırı Yüklemesi

Bu durumda, aynı ada ancak farklı parametrelere sahip 2 yöntem yazarak sorunu çözebiliriz:
public class Jarvis {

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

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }
}
Buna yöntem aşırı yüklemesi denir. Yöntem aşırı yükleme, programımızın daha esnek olmasını ve çeşitli çalışma biçimlerini barındırmasını sağlar. Nasıl çalıştığını gözden geçirelim:
public class Jarvis {

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

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

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
        jarvis.sayHi("Tony Stark", "Captain America");
    }
}
Konsol çıktısı:
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
Mükemmel, her iki sürüm de çalıştı. :) Ama sorunu çözmedik! Ya üç misafir varsa? Elbette sayHi() yöntemini tekrar aşırı yükleyebiliriz, böylece üç misafir adını kabul edebilir. Ama 4 veya 5 olabilir. Sonsuza kadar. SayHi() yöntemini bir milyon kez aşırı yüklemeden Jarvis'e herhangi bir sayıda adı işlemeyi öğretmenin daha iyi bir yolu yok mu ? :/ Elbette var! Olmasaydı, sizce Java dünyadaki en popüler programlama dili olur muydu? ;)
public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ". How are you?");
    }
}
( String...names ) parametre olarak kullanıldığında, yönteme bir Dizeler koleksiyonunun aktarılacağını belirtir. Kaç tane olacağını önceden belirtmek zorunda değiliz, bu yüzden artık yöntemimiz çok daha esnek:
public class Jarvis {

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

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
    }
}
Konsol çıktısı:
Good evening, Tony Stark. How are you?
Good evening, Captain America. How are you?
Good evening, Black Widow. How are you?
Good evening, Hulk. How are you?
Buradaki bazı kodlar size yabancı gelebilir, ancak bunun için endişelenmeyin. Özünde basit: yöntem sırayla her ismi alır ve her konuğu selamlar! Artı, herhangi bir sayıda geçirilen diziyle çalışacaktır! İki, on, hatta bin—yöntem herhangi bir sayıda misafirle düzgün çalışacaktır. Yöntemi tüm olasılıklar için aşırı yüklemekten çok daha uygun, sence de öyle değil mi? :) İşte bir başka önemli nokta: bağımsız değişkenlerin sırası önemlidir! Diyelim ki yöntemimiz bir String ve bir sayı alıyor:
public class Person {

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

    public static void main(String[] args) {
        sayYourAge("My age is ", 33);
        sayYourAge(33, "My age is "); // Error!
    }
}
Person sınıfının sayYourAge yöntemi girdi olarak bir dize ve bir sayı alıyorsa , programın bunları belirli bir sırada iletmesi gerekir! Bunları farklı bir sırayla geçirirsek derleyici hata verir ve kişi yaşını söyleyemez. Bu arada, son derste ele aldığımız yapıcılar da yöntemlerdir! Ayrıca bunları aşırı yükleyebilirsiniz (yani, farklı parametre kümelerine sahip birkaç oluşturucu oluşturun) ve aktarılan bağımsız değişkenlerin sırası onlar için de temelde önemlidir. Bunlar gerçek yöntemler! :)

Yine parametrelerle ilgili

Evet, üzgünüm, onlarla işimiz henüz bitmedi. :) Şimdi çalışacağımız konu çok önemli. Gelecekteki her görüşmede bunun size sorulma olasılığı %90'dır! Argümanları yöntemlere iletmek hakkında konuşalım. Basit bir örnek düşünün:
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 = 2018;

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

        timeMachine.goToPast(currentYear);
        System.out.println("How about now?");
        System.out.println(currentYear);
    }
}
Zaman makinesinin iki yöntemi vardır. Her ikisi de içinde bulunulan yılı temsil eden sayıyı girdi olarak alır ve (geçmişe veya geleceğe gitmek isteyip istemediğimize bağlı olarak) değerini artırır veya azaltır. Ancak konsol çıktısından da görebileceğiniz gibi yöntem çalışmıyor! Konsol çıktısı:
What year is it?
2018
How about now?
2018
currentYear değişkenini goToPast() yöntemine geçirdik , ancak değeri değişmedi. 2018'deydik ve burada kaldık. Ama neden? :/ Çünkü Java'daki ilkel öğeler, yöntemlere değere göre iletilir. Bu ne anlama gelir? goToPast() yöntemini çağırıp ona currentYear (=2018) int değişkenini ilettiğimizde , yöntem currentYear değişkeninin kendisini değil, onun bir kopyasını alır. Elbette bu kopyanın değeri de 2018'dir, ancak kopyada yapılan herhangi bir değişiklik orijinal currentYear değişkenimizi hiçbir şekilde etkilemez! Şimdi kodumuzu daha açık hale getirelim ve currentYear ile neler olduğunu görelim:
public class TimeMachine {

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

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

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

        System.out.println("What was the year when the program started?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And what year is it now?");
        System.out.println(currentYear);
    }
}
Konsol çıktısı:
What was the year when the program started?
2018
The goToPast method has started running!
currentYear inside the goToPast method (at the beginning) = 2018
currentYear inside the goToPast method (at the end) = 2008
And what year is it now?
2018
Bu açıkça goToPast() yöntemine iletilen değişkenin currentYear öğesinin yalnızca bir kopyası olduğunu açıkça gösterir . Ve kopyanın değiştirilmesi "orijinal" değeri etkilemez. "Referansa göre geç" tam tersi anlamına gelir. Kediler üzerinde pratik yapalım! Demek istediğim, bir kedi örneği kullanarak referansa göre geçişin nasıl göründüğüne bakalım. :)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Şimdi zaman makinemizin yardımıyla dünyanın ilk zamanda yolculuk yapan kedisi Smudge'ı geçmişe ve geleceğe göndereceğiz ! TimeMachine sınıfını Cat nesneleri ile çalışacak şekilde değiştirelim ;
public class TimeMachine {

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

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
Artık yöntemler sadece geçen sayıyı değiştirmiyor. Bunun yerine, belirli Cat'in yaş alanını değiştirirler . Bunun bizim için ilkellerde işe yaramadığını hatırlayacaksınız, çünkü orijinal sayı değişmedi. Bakalım ne olacak!
public static void main(String[] args) {

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

    System.out.println("How old was Smudge when the program started?");
    System.out.println(smudge.age);

    timeMachine.goToFuture(smudge);
    System.out.println("How about now?");
    System.out.println(smudge.age);

    System.out.println("Holy smokes! Smudge has aged 10 years! Back up quickly!");
    timeMachine.goToPast(smudge);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(smudge.age);
}
Konsol çıktısı:
How old was Smudge when the program started running?
5
How about now?
15
Holy smokes! Smudge has aged 10 years! Back up quickly!
Did it work? Have we returned the cat to its original age?
5
Vay! Şimdi yöntem farklı bir şey yaptı: kedimiz ciddi şekilde yaşlandı ama sonra tekrar gençleşti! :) Nedenini anlamaya çalışalım. İlkel örnekten farklı olarak, nesneler bir yönteme geçirildiğinde referans olarak geçirilirler. ChangeAge() yöntemine orijinal leke nesnesine bir başvuru iletildi . Bu nedenle, yöntemin içinde smudge.age'i değiştirdiğimizde , nesnemizin depolandığı aynı bellek alanına atıfta bulunuyoruz. Bu, başlangıçta oluşturduğumuz Smudge'a bir göndermedir. Buna "referans yoluyla geçmek" denir! Ancak, referansları olan her şey o kadar kolay değildir. :) Örneğimizi değiştirmeyi deneyelim:
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 smudge = new Cat(5);

        System.out.println("How old was Smudge when the program started?");
        System.out.println(smudge.age);

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

        System.out.println ("And if you try going back?");
        timeMachine.goToPast(smudge);
        System.out.println(smudge.age);
    }
}
Konsol çıktısı:
How old was Smudge when the program started running?
5
Smudge went to the future! Has his age changed?
5
And if you try going back?
5
Yine çalışmıyor! О_О Ne olduğunu anlayalım. :) goToPast / goToFuture yöntemleri ve referansların nasıl çalıştığı ile ilgili her şeye sahiptir . Şimdi, dikkatinizi lütfen! Referansların ve yöntemlerin nasıl çalıştığı hakkında anlaşılması gereken en önemli şey budur. Gerçek şu ki, goToFuture(Cat cat) yöntemini çağırdığımızda , iletilen referansın kendisi değil, cat nesnesine yapılan referansın bir kopyasıdır. Bu nedenle, bir yönteme bir nesne ilettiğimizde, nesneye iki referans vardır. Bu, olup biteni anlamak için çok önemlidir. İşte tam da bu yüzden son örneğimizde kedinin yaşı değişmedi. Önceki örnekte, yaşı değiştirirken, basitçe goToFuture () işlevine iletilen referansı aldık.yöntemini kullandı ve bellekteki nesneyi bulmak ve yaşını değiştirmek için kullandı ( cat.age += 10 ). Ama şimdi, goToFuture() yönteminin içinde, yeni bir nesne yaratıyoruz ( cat = new Cat(cat.age) ) ve bu nesneye, yönteme iletilen referans kopyanın aynısı atanır. Sonuç olarak:
  • İlk referans ( Cat smudge = new Cat (5) ), orijinal kediye (5 yaşında) işaret eder.
  • Daha sonra cat değişkenini goToPast() metoduna geçirip ona yeni bir nesne atadığımızda referans kopyalandı.
Bu da bizi nihai sonuca getirdi: iki farklı nesneye işaret eden iki referans. Ama sadece birinin yaşını değiştirdik (yöntemin içinde yaratılan).
cat.age += 10;
Ve tabii ki, main() yönteminde konsolda kedinin yaşı olan smudge.age'in değişmediğini görebiliriz . Ne de olsa, smudge hala 5 yaşındaki eski, orijinal nesneyi işaret eden bir referans değişkeni ve biz o nesneyle hiçbir şey yapmadık. Tüm yaş değişikliklerimiz yeni nesne üzerinde yapıldı. Böylece, nesnelerin yöntemlere referans olarak iletildiği ortaya çıkıyor. Nesnelerin kopyaları asla otomatik olarak oluşturulmaz. Bir cat nesnesini bir metoda aktarırsanız ve yaşını değiştirirseniz, onun yaşını da değiştirmiş olursunuz. Ancak, değerler atanırken ve/veya yöntemler çağrılırken referans değişkenleri kopyalanır! Primitifleri geçirmekle ilgili söylediğimizi burada tekrar edelim: " changeInt() yöntemini çağırıp int'i geçtiğimizdex (=15) değişkeninde , yöntem x değişkeninin kendisini değil, onun bir kopyasını alır. Bu nedenle, kopyada yapılan herhangi bir değişiklik orijinal x'imizi etkilemez .Java'da argümanların nasıl iletildiği konusunda (deneyimli geliştiriciler arasında bile) birçok kez tartışmaya devam edeceksiniz. Ancak, artık tam olarak nasıl çalıştığını biliyorsunuz. Aynen böyle devam! :) Öğrendiklerinizi pekiştirmek için Java Kursumuzdan bir video dersi izlemenizi öneririz.
Yorumlar
  • Popüler
  • Yeni
  • Eskimiş
Yorum bırakmak için giriş yapmalısınız
Bu sayfada henüz yorum yok