CodeGym /จาวาบล็อก /สุ่ม /การประกาศวิธีการ
John Squirrels
ระดับ
San Francisco

การประกาศวิธีการ

เผยแพร่ในกลุ่ม
สวัสดี! คุณทราบเกี่ยวกับการสร้างชั้นเรียนของคุณเองด้วยฟิลด์และเมธอดแล้ว ตอนนี้เราจะอาศัยวิธีการ
การประกาศเมธอด - 1
แน่นอน เราได้ทำสิ่งนี้มาแล้วมากกว่าหนึ่งครั้งในบทเรียนของเรา แต่หลักๆ แล้วเราได้กล่าวถึงเรื่องทั่วไป วันนี้เราจะมาแยกย่อยวิธีการต่างๆ และศึกษาว่ามันทำมาจากอะไร วิธีต่างๆ ในการสร้างมัน และวิธีการจัดการทั้งหมด :) ไปกันเถอะ!

การประกาศวิธีการ

รหัสทั้งหมดที่กำหนดเมธอดเรียกว่าการประกาศเมธอด รูปแบบทั่วไปของการประกาศเมธอดสามารถอธิบายได้ดังนี้:

access modifier, return type, method name (parameter list) {
    // method body
}
ให้ดูที่การประกาศของเมธอดต่างๆ ของDogคลาส ดังตัวอย่าง

public class Dog {

   String name;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {
       Dog max = new Dog("Max");
       max.woof();

   }

   public void woof() {
       System.out.println("A dog named " + name + " says \"Woof, woof!\"");
   }

   public void run(int distanceInFeet) {
       System.out.println("A dog named " + name + " ran " + distanceInFeet + " feet!");
   }

   public String getName() {
       return name;
   }
}

1. ตัวแก้ไขการเข้าถึง

ตัวแก้ไขการเข้าถึงจะถูกระบุก่อนเสมอ เมธอดของคลาส ทั้งหมดDogถูกทำเครื่องหมายด้วยตัวดัดแปลงสาธารณะ ซึ่งหมายความว่าเราสามารถเรียกพวกเขาจากคลาสอื่น:

public class Main {

   public static void main(String[] args) {

       Dog butch = new Dog("Butch");
       butch.run(100);
   }

}
อย่างที่คุณเห็นDogวิธีการของคลาสสามารถเข้าถึงได้ง่ายในMainคลาส สิ่งนี้เป็นไปได้เนื่องจากตัวดัดแปลงสาธารณะ ใน Java มีตัวปรับแต่งอื่นๆ พวกเขาไม่อนุญาตให้ใช้เมธอดในคลาสอื่น เราจะพูดถึงพวกเขาในบทเรียนอื่นๆ สิ่งสำคัญที่ต้องจำไว้คือสิ่งที่ตัวแก้ไขรับผิดชอบ: เข้าถึงเมธอดในคลาสอื่นได้หรือไม่ :)

2. คำหลักคงที่

หนึ่งในDogวิธีการ , main()ถูกทำเครื่องหมายด้วยคำหลักคงที่ นอกจากนี้ยังเป็นส่วนหนึ่งของการประกาศเมธอด และเรารู้ความหมายของมันแล้ว เราไม่ได้พูดถึงสิ่งนี้ในเทมเพลตการประกาศเมธอดที่ให้ไว้ในตอนต้นของบทเรียน เนื่องจากเป็นทางเลือก หากมีการระบุไว้ จะต้องมาหลังตัวแก้ไขการเข้าถึง จำได้ไหมว่าในบทเรียนล่าสุดเราได้พูดถึงตัวแปรแบบคงที่ (คลาส)? เมื่อนำไปใช้กับเมธอด คำหลักนี้จะมีความหมายใกล้เคียงกัน ถ้าเมธอดเป็นแบบสแตติกก็สามารถใช้ได้โดยไม่ต้องอ้างอิงถึงอ็อบเจกต์เฉพาะของคลาส และแน่นอน คุณไม่จำเป็นต้องมีDogวัตถุเพื่อรันmain()เมธอดแบบสแตติกในDogระดับ. มันจะทำงานได้ดีโดยไม่มีใคร ถ้าเมธอดนี้ไม่คงที่ อันดับแรกเราต้องสร้างอ็อบเจกต์เพื่อเรียกใช้งาน

3. คืนค่า

หากเมธอดของเราควรคืนค่าบางอย่าง เราจะระบุประเภทของค่าส่งคืน เห็นได้ชัดจากตัวอย่างของgetName()getter:

public String getName() {
   return name;
}
มันส่งคืนStringวัตถุ หากเมธอดไม่ส่งคืนอะไรเลย จะใช้ คีย์เวิร์ด voidwoof() แทน เช่นเดียวกับ เมธอด:

public void woof() {
   System.out.println("A dog named " + name + " says \"Woof, woof!\"");
}

วิธีการที่มีชื่อเดียวกัน

มีบางสถานการณ์ที่เราต้องการเรียกใช้เมธอดหลายวิธี ทำไมไม่สร้างปัญญาประดิษฐ์ของเราเอง? Amazon มี Alexa, Apple มี Siri แล้วทำไมเราจะไม่มีล่ะ :) ในภาพยนตร์เรื่อง Iron Man โทนี่ สตาร์กสร้างจาร์วิสปัญญาประดิษฐ์ที่น่าทึ่งของเขาเอง เรามายกย่องตัวละครที่ยอดเยี่ยมและตั้งชื่อ AI ของเราเพื่อเป็นเกียรติแก่เขา :) สิ่งแรกที่เราต้องทำคือสอนให้จาร์วิสกล่าวทักทายผู้ที่เข้ามาในห้อง (มันคงเป็นเรื่องแปลกหากสติปัญญาที่น่าทึ่งกลายเป็นคนไม่สุภาพ)

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");
   }
}
เอาต์พุตคอนโซล: สวัสดี โทนี่ สตาร์ค คุณเป็นอย่างไร? ดีมาก! Jarvis สามารถต้อนรับแขกได้แล้ว แน่นอนว่าโทนี่สตาร์คเจ้านายของเขาบ่อยกว่าที่จะเป็น แต่ถ้าเขาไม่ได้มาคนเดียวล่ะ! แต่sayHi()วิธีการของเรายอมรับเพียงหนึ่งข้อโต้แย้ง ดังนั้นมันจึงทักทายได้แค่คนเดียวที่เข้ามาในห้อง และจะไม่สนใจอีกคนหนึ่ง ไม่สุภาพมากตกลง? :/ ในกรณีนี้ เราสามารถแก้ปัญหาได้โดยการเขียน 2 method โดยใช้ชื่อเดียวกันแต่พารามิเตอร์ต่างกัน:

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 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");
   }
}
เอาต์พุตคอนโซล: สวัสดี โทนี่ สตาร์ค คุณเป็นอย่างไร? สวัสดีตอนเย็น โทนี่ สตาร์คและกัปตันอเมริกา คุณเป็นอย่างไร? ยอดเยี่ยมทั้งสองเวอร์ชันใช้งานได้ :) แต่เราไม่ได้แก้ปัญหา! เกิดอะไรขึ้นถ้ามีแขกสามคน? แน่นอน เราสามารถโอเวอร์โหลดsayHi()เมธอดอีกครั้ง เพื่อให้ยอมรับชื่อแขกสามชื่อ แต่อาจมี 4 หรือ 5 ไปจนถึงอนันต์ ไม่มีวิธีใดที่ดีกว่าในการสอน Jarvis ให้จัดการกับชื่อจำนวนเท่าใดก็ได้ โดยไม่ต้องใช้sayHi()เมธอดเกินล้านครั้ง () :/ มีแน่นอน! ถ้าไม่มี คุณคิดว่า Java จะเป็นภาษาโปรแกรมที่ได้รับความนิยมมากที่สุดในโลกหรือไม่? ;)

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");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
เมื่อใช้ ( String... names ) เป็นพารามิเตอร์ แสดงว่าชุดของ Stringsจะถูกส่งผ่านไปยังเมธอด เราไม่ต้องระบุล่วงหน้าว่าจะมีกี่รายการ ดังนั้นตอนนี้วิธีการของเราจึงยืดหยุ่นมากขึ้น:

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");
   }
}
เอาต์พุตคอนโซล: สวัสดี โทนี่ สตาร์ค คุณเป็นอย่างไร? สวัสดีตอนเย็นกัปตันอเมริกา คุณเป็นอย่างไร? สวัสดีตอนเย็น แม่ม่ายดำ คุณเป็นอย่างไร? สวัสดีตอนเย็นฮัลค์ คุณเป็นอย่างไร? ภายในเมธอด เราทำซ้ำอาร์กิวเมนต์ทั้งหมดและแสดงวลีที่มีชื่อ ที่นี่เราใช้for-eachการวนซ้ำแบบง่าย (ซึ่งคุณเคยเห็นมาก่อน) มันสมบูรณ์แบบที่นี่เพราะสัญกรณ์ ( String... names ) หมายความว่าคอมไพเลอร์ใส่อาร์กิวเมนต์ที่ผ่านทั้งหมดลงในอาร์เรย์ เป็นผลให้เราสามารถทำงานกับชื่อ ตัวแปรในขณะที่เราจะทำงานกับอาร์เรย์ รวมถึงการวนซ้ำผ่านอาร์เรย์ นอกจากนี้ยังสามารถทำงานร่วมกับสตริงที่ส่งผ่านจำนวนเท่าใดก็ได้! สอง สิบ หรือพัน—วิธีการนี้จะใช้ได้ผลกับแขกจำนวนเท่าใดก็ได้ สะดวกกว่าวิธีการมากเกินไปสำหรับความเป็นไปได้ทั้งหมด คุณไม่คิดเหรอ? :) นี่เป็นอีกตัวอย่างหนึ่งของวิธีการโอเวอร์โหลด ลองให้printInfoFromDatabase()วิธีการ ของจาร์วิส จะแสดงข้อมูลเกี่ยวกับบุคคลจากฐานข้อมูล หากฐานข้อมูลระบุว่าบุคคลนั้นเป็นซูเปอร์ฮีโร่หรือซูเปอร์วายร้าย เราจะแสดงข้อมูลนั้น:

public class Jarvis {

   public void printInfoFromDatabase (String bio) {

       System.out.println(bio);
   }

   public void printInfoFromDatabase(String bio, boolean isEvil, String nickname) {

       System.out.println(bio);
       if (!isEvil) {
           System.out.println("Also known as the superhero " + nickname);
       } else {
           System.out.println("Also known as the supervillain " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Laura Palmer. Date of birth: July 22, 1972. Twin Peaks, Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Max Eisenhardt. Height: 15.6 ft. Weight: 189 lbs. ", true, "Magneto");
   }
}
เอาท์พุต: ลอรา พาล์มเมอร์ วันเกิด: 22 กรกฎาคม 2515 Twin Peaks, Washington Max Eisenhardt ส่วนสูง: 15.6 ฟุต น้ำหนัก: 189 ปอนด์ เรียกอีกอย่างว่า supervillain Magneto So พฤติกรรมของวิธีการของเราขึ้นอยู่กับข้อมูลที่เราส่งไปให้ ประเด็นสำคัญอีกประการหนึ่ง: ลำดับข้อโต้แย้งมีความสำคัญ! สมมติว่าวิธีการของเราใช้สตริงและตัวเลข:

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ของคลาสsayYourAge()ใช้สตริงและตัวเลขเป็นอินพุต นี่คือคำสั่งที่ต้องส่งผ่านอาร์กิวเมนต์เหล่านี้ไปยังเมธอด! หากเราส่งตามลำดับที่แตกต่างกัน คอมไพเลอร์จะสร้างข้อผิดพลาดและบุคคลนั้นจะไม่สามารถบอกอายุของเขาได้ อย่างไรก็ตาม ตัวสร้างที่เรากล่าวถึงในบทเรียนที่แล้วก็เป็นวิธีการเช่นกัน! คุณยังสามารถโอเวอร์โหลดพวกมันได้ (เช่น สร้างคอนสตรัคเตอร์หลายตัวด้วยชุดพารามิเตอร์ที่แตกต่างกัน) และลำดับของอาร์กิวเมนต์ที่ส่งผ่านก็มีความสำคัญสำหรับพวกมันเช่นกัน เป็นวิธีการที่แท้จริง! :)

วิธีเรียกใช้เมธอดด้วยพารามิเตอร์ที่คล้ายกัน

ดังที่คุณทราบnullเป็นคำสำคัญในภาษาจาวา สิ่งสำคัญคือต้องเข้าใจว่าไม่ใช่nullวัตถุหรือประเภทข้อมูล ลองนึกภาพว่าเรามีPersonคลาสและintroduce()เมธอดซึ่งประกาศชื่อและอายุของบุคคลนั้น นอกจากนี้ยังสามารถส่งอายุเป็นข้อความหรือตัวเลขได้

public class Person {

   public void introduce(String name, String age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person alex = new Person();
       alex.introduce ("Alex", "twenty-one");

       Person mary = new Person();
       mary.introduce("Mary", 32);
   }
}
เราคุ้นเคยกับการโอเวอร์โหลดอยู่แล้ว ดังนั้นเราจึงรู้ว่าทั้งสองวิธีจะทำงานตามที่ควรจะเป็น: ฉันชื่ออเล็กซ์ ฉันอายุยี่สิบเอ็ด ฉันชื่อแมรี่ อายุของฉันคือ 32 แต่จะเกิดอะไรขึ้นถ้าเราส่งnullเป็นพารามิเตอร์ที่สองแทนที่จะเป็นสตริงหรือตัวเลข

public static void main(String[] args) {

   Person victor = new Person();
   victor.introduce("Victor", null);// Ambiguous method call!
}
เราจะได้รับข้อผิดพลาดในการรวบรวม! อะไรทำให้เกิดสิ่งนี้และอะไรคือ "ความคลุมเครือ" ในความเป็นจริงมันง่ายมาก ปัญหาคือเรามีเมธอดสองเวอร์ชัน: เวอร์ชันหนึ่งมี a Stringเป็นอาร์กิวเมนต์ที่สอง และอีกเวอร์ชันมี an Integerเป็นอาร์กิวเมนต์ที่สอง แต่ a Stringและ an Integerสามารถเป็นได้ทั้งคู่null! เนื่องจากเป็นประเภทการอ้างอิง จึงnullเป็นค่าเริ่มต้นสำหรับทั้งคู่ นั่นเป็นเหตุผลที่ในสถานการณ์นี้ คอมไพเลอร์ไม่สามารถระบุได้ว่าควรจะเรียกเมธอดเวอร์ชันใด วิธีแก้ปัญหานี้ค่อนข้างง่าย Nullสามารถแปลงเป็นประเภทการอ้างอิงเฉพาะได้อย่างชัดเจน ดังนั้น เมื่อคุณเรียกใช้เมธอด คุณสามารถระบุประเภทข้อมูลที่คุณต้องการสำหรับอาร์กิวเมนต์ที่สองในวงเล็บได้! คอมไพเลอร์จะเข้าใจ "คำใบ้" ของคุณและจะเรียกใช้เมธอดที่ถูกต้อง:

public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Method with a string and a number!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", (String) null);
   }
}
ผลลัพธ์: วิธีการที่มีสองสาย! ฉันชื่อวิคเตอร์ อายุของฉันเป็น null โปรดทราบว่าหากพารามิเตอร์ number เป็น primitive intแทนที่จะเป็นอินสแตนซ์ของประเภทการอ้างอิงจำนวนเต็ม จะไม่มีข้อผิดพลาดดังกล่าว

public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Method with a string and a number!!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", null);
   }
}
คุณเดาได้ไหมว่าทำไม หากคุณเดาว่าทำไม ทำได้ดีมาก! :) เพราะดั้งเดิมไม่nullสามารถ ตอนนี้คอมไพเลอร์มีทางเลือกเดียว คือการเรียกใช้introduce()เมธอดด้วยสองสตริง นี่คือเวอร์ชั่นของเมธอดที่จะรันทุกครั้งที่เมธอดถูกเรียกใช้

อ่านเพิ่มเติม:

ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION