1. วัตถุและคลาส

วันนี้คุณจะได้เรียนรู้เล็กน้อยเกี่ยวกับวิธีการทำงานของโปรแกรม Java ทั่วไป นี่คือข่าวใหญ่: ทุกโปรแกรม Java ประกอบด้วยคลาสและออบเจกต์

คุณรู้อยู่แล้วว่าคลาสคืออะไร แต่ออบเจกต์คืออะไร

ฉันจะเริ่มต้นด้วยการเปรียบเทียบ จินตนาการว่าคุณต้องการต่อเรือลำเล็กๆ ขั้นแรกคุณต้องสร้างพิมพ์เขียวแล้วส่งให้กับโรงงาน ซึ่งเรือจะถูกสร้างขึ้นตามพิมพ์เขียว หรืออาจจะเป็นโหล หรือเรือได้มากเท่าที่คุณต้องการ เรือรบที่เหมือนกันหลายสิบลำถูกสร้างขึ้นตามพิมพ์เขียวเดียว นั่นคือสิ่งสำคัญที่นี่

มันเหมือนกันในการเขียนโปรแกรม Java

พิมพ์เขียว

โปรแกรมเมอร์ก็เหมือนนักออกแบบ นักออกแบบสร้างพิมพ์เขียว และโปรแกรมเมอร์ Java เขียนคลาส ชิ้นส่วนถูกสร้างขึ้นตามพิมพ์เขียว และวัตถุถูกสร้างขึ้นตามคลาส

ขั้นแรก เราเขียนคลาส (สร้างพิมพ์เขียว) จากนั้น ขณะที่โปรแกรมทำงาน เครื่อง Java จะสร้างออบเจกต์ตามคลาสเหล่านี้ ในลักษณะเดียวกับที่สร้างเรือจากพิมพ์เขียว

มีพิมพ์เขียวเพียงอันเดียว แต่สามารถมีได้หลายลำ เรือมีความแตกต่างกัน — มีชื่อต่างกันและบรรทุกสินค้าต่างกัน แต่มีความคล้ายคลึงกันมาก: พวกเขาทั้งหมดมีการออกแบบเดียวกันและสามารถทำงานที่คล้ายกันได้

หรือนี่คือการเปรียบเทียบอื่น ...

จอมปลวก

จอมปลวกเป็นตัวอย่างที่ดีของการโต้ตอบของวัตถุ มีมดสามประเภทในจอมปลวกง่ายๆ คือ มดราชินี ทหาร และคนงาน

จำนวนมดแต่ละชั้นจะแตกต่างกัน มีราชินีเพียงตัวเดียวสำหรับจอมปลวกทั้งหมด แต่มีทหารหลายสิบคนและมดงานหลายร้อยตัว สามคลาสและวัตถุนับร้อย มดมีปฏิสัมพันธ์ซึ่งกันและกัน - กับมดในคลาสเดียวกันและกับมดในคลาสอื่น ๆ - ตามกฎที่เข้มงวด

นี่คือตัวอย่างที่สมบูรณ์แบบ ทุกอย่างเป็นแบบนี้ในโปรแกรมทั่วไป มีวัตถุหลักที่สร้างวัตถุของคลาสอื่นทั้งหมด วัตถุเริ่มมีปฏิสัมพันธ์ซึ่งกันและกันและกับ "โลกภายนอก" ของโปรแกรม พฤติกรรมของอ็อบเจกต์ถูกฮาร์ดโค้ดไว้ภายใน

การเปรียบเทียบทั้งสองนี้เป็นสองด้านของเหรียญเดียวกัน ความจริงอยู่ตรงกลาง ตัวอย่างแรก (เกี่ยวกับพิมพ์เขียวและเรือ) แสดงความสัมพันธ์ระหว่างคลาสและวัตถุของคลาสนั้น นี่คือการเปรียบเทียบที่แข็งแกร่ง ตัวอย่างที่สอง (เกี่ยวกับจอมปลวก) แสดงความสัมพันธ์ระหว่างคลาสที่เขียนและออบเจกต์ที่มีอยู่ขณะที่โปรแกรมทำงาน

ก่อนอื่นคุณต้องเขียนคลาสสำหรับทุกออบเจกต์ที่จะมีอยู่ในโปรแกรม จากนั้นจึงอธิบายวิธีการโต้ตอบ ใช่ ถูกต้อง แต่มันง่ายกว่าที่คิด

ใน Java เอนทิตีทั้งหมดเป็นออบเจกต์ในขณะรันไทม์ และการเขียนโปรแกรมคือการอธิบายวิธีต่างๆ ที่ออบเจ็กต์โต้ตอบ ออบเจกต์เพียงเรียกเมธอดของกันและกันและส่งข้อมูลที่จำเป็นไปให้

เอกสาร

และคุณจะรู้ได้อย่างไรว่าข้อมูลใดที่จะส่งผ่านไปยังเมธอด? คนที่มาก่อนคุณคิดทุกอย่าง

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

ในการใช้คลาส คุณต้องมีแนวคิดทั่วไปว่าคลาสนั้นใช้ทำอะไร และคุณจำเป็นต้องรู้ให้แน่ชัดว่าแต่ละวิธีทำหน้าที่อะไร แต่คุณไม่จำเป็นต้องรู้เลยว่ามันทำอย่างไร มันเหมือนไม้กายสิทธิ์

มาดูรหัสสำหรับการคัดลอกไฟล์:

การคัดลอกไฟล์ c:\\data.txt ไปยังไฟล์ c:\\result.txt
package com.codegym.lesson2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopy
{
   public static void main(String[] args) throws IOException
   {
      FileInputStream fileInputStream = new FileInputStream("c:\\data.txt");
      FileOutputStream fileOutputStream = new FileOutputStream("c:\\result.txt");

      while (fileInputStream.available() > 0)
      {
         int data = fileInputStream.read();
         fileOutputStream.write(data);
      }

      fileInputStream.close();
      fileOutputStream.close();
   }
}

ถ้าคุณอ่านรหัสนี้ทีละบรรทัด คุณก็จะเดาได้ว่ามันใช้ทำอะไรโดยทั่วไป แม้ว่าจะต้องใช้ประสบการณ์และการฝึกฝน หลังจากนั้นไม่นานรหัสนี้จะดูเหมือนคุ้นเคยและเข้าใจได้สำหรับคุณ


2. การออกแบบโปรแกรม

การออกแบบโปรแกรมเป็นศิลปะทั้งหมด มันง่ายและยากพร้อมกัน ง่ายเพราะไม่มีกฎหมายที่เข้มงวด: อนุญาตให้ใช้สิ่งใดก็ตามที่ไม่ได้รับอนุญาต และนั่นก็เป็นสิ่งที่ทำให้ยากด้วย มีหลายวิธีที่จะทำบางสิ่ง และมันไม่ง่ายเลยที่จะหาวิธีที่ดีที่สุด

การออกแบบโปรแกรมก็เหมือนการเขียนหนังสือ ด้านหนึ่ง คุณแค่เขียนตัวอักษร คำ และประโยค ในทางกลับกัน โครงเรื่อง ตัวละคร ความขัดแย้งภายใน ความขัดแย้ง สไตล์การเล่าเรื่อง การวางอุบาย ฯลฯ มีความสำคัญ

สิ่งสำคัญคือต้องเข้าใจว่าคุณกำลังเขียนโค้ดเพื่อใคร และคุณเขียนโค้ดให้กับโปรแกรมเมอร์คนอื่น

การพัฒนาผลิตภัณฑ์หมายถึงการเปลี่ยนแปลงอย่างหลีกเลี่ยงไม่ได้: บางอย่างถูกเพิ่มที่นี่ บางอย่างถูกลบออกที่นั่น บางอย่างได้รับการออกแบบใหม่ นั่นเป็นวิธีที่โครงการขนาดใหญ่ ใหญ่โตมโหฬาร เกิดจากการทำซ้ำเล็กๆ น้อยๆ

สิ่งที่สำคัญที่สุดสำหรับโค้ดก็คือโปรแกรมเมอร์คนอื่นๆ จะต้องเข้าใจโค้ดนั้น รหัสที่ไม่ถูกต้องที่เข้าใจสามารถแก้ไขได้ ไม่สามารถปรับปรุงโค้ดที่ถูกต้องแต่ไม่สามารถเข้าใจได้  สิ่งที่คุณทำได้คือทิ้งมันไป

ดังนั้นคุณจะเขียนโค้ดที่ดีและสะอาดได้อย่างไร

การทำเช่นนี้ต้องใช้สามสิ่ง:

  • การเขียนโค้ดภายในเมธอดที่ดีและเข้าใจได้ — นี่เป็นข้อกำหนดที่ง่ายที่สุด
  • การตัดสินใจว่าควรรวมเอนทิตีใดไว้ในโปรแกรม
  • แยกโปรแกรมออกเป็นส่วนตรรกะอย่างถูกต้อง

เบื้องหลังแนวคิดเหล่านี้คืออะไร?

การเขียนโค้ดที่ดีภายในวิธีการ

หากคุณมีทักษะภาษาอังกฤษขั้นพื้นฐาน คุณอาจสังเกตเห็นว่าบางครั้งการอ่านโค้ดเป็นประโยคภาษาอังกฤษนั้นง่ายเพียงใด:

  • class Cat extends Pet— นี่หมายความว่าคลาสแมวขยายคลาสสัตว์เลี้ยง
  • while(stream.ready())— ตราบใดที่สตรีมพร้อม...
  • if (a<b) return a; else return b— ถ้าаน้อยกว่าbให้คืนаมิฉะนั้นbคืน

นี่คือเจตนา Java เป็นหนึ่งในหลายภาษาที่ทำให้ง่ายต่อการเขียนโค้ดการจัดทำเอกสารด้วยตนเอง นั่นคือโค้ดที่เข้าใจได้โดยไม่ต้องแสดงความคิดเห็น ในโค้ด Java ที่ดี มีหลายวิธีอ่านเหมือนกับประโยคภาษาอังกฤษ

เมื่อเขียนโค้ด งานของคุณคือทำให้ง่ายและกระชับที่สุด ลองคิดดูว่าโค้ดของคุณอ่านง่ายไหม และคุณจะเริ่มไปในทิศทางที่ถูกต้อง

ใน Java เป็นธรรมเนียมที่จะต้องเขียนโค้ดที่อ่านง่าย โค้ดทั้งหมดสำหรับเมธอดจะพอดีกับหน้าจอเดียว (เช่น 20-30 บรรทัด) นี่เป็นบรรทัดฐานสำหรับชุมชน Java ทั้งหมด หากสามารถปรับปรุงโค้ดได้ก็ควรปรับปรุง

วิธีที่ดีที่สุดในการเรียนรู้วิธีเขียนโค้ดที่ดีคือการฝึกฝน เขียนโค้ดจำนวนมาก ศึกษาโค้ดของผู้อื่น และขอให้เพื่อนร่วมงานที่มีประสบการณ์ตรวจสอบโค้ดของคุณ

และจำไว้ว่าช่วงเวลาที่คุณบอกตัวเองว่า "พอแล้ว" การเติบโตของคุณจะหยุดลง

การตัดสินใจว่าควรรวมเอนทิตีใดไว้ในโปรแกรม

คุณต้องเขียนโค้ดที่โปรแกรมเมอร์คนอื่นสามารถเข้าใจได้ ถ้าโปรแกรมเมอร์ 9 ใน 10 คนต้องการรวมคลาส A, B และ C ไว้ในการออกแบบโปรแกรม คุณก็ควรสร้างคลาส A, B และ C ในโปรแกรมของคุณด้วย คุณต้องเขียนโค้ดที่ผู้อื่นสามารถเข้าใจได้

ยอดเยี่ยม ใช้งานได้ รวดเร็ว แต่รหัสที่ไม่ได้มาตรฐานคือรหัสที่ไม่ดี

คุณต้องศึกษาโครงการของผู้อื่น: นี่เป็นวิธีที่ดีที่สุด เร็วที่สุด และง่ายที่สุดในการดื่มด่ำกับภูมิปัญญาทั้งหมดที่สะสมในอุตสาหกรรมไอทีมานานหลายทศวรรษ

และอีกอย่าง คุณมีสิทธิ์เข้าถึงโปรเจ็กต์ที่ยอดเยี่ยม เป็นที่นิยม และมีเอกสารครบถ้วน — Java SDK เริ่มต้นด้วยมัน

วิเคราะห์ชั้นเรียนและวิธีการจัดระเบียบ ลองนึกถึงสาเหตุที่บางวิธีคงที่และบางวิธีไม่เป็นเช่นนั้น เหตุใดเมธอดจึงมีพารามิเตอร์เฉพาะที่มี แต่ไม่มีอย่างอื่น เหตุใดเมธอดเหล่านี้จึงถูกต้อง และเหตุใดคลาสจึงตั้งชื่อตามชื่อ และเหตุใดจึงมีอยู่ในแพ็คเกจเฉพาะ

เมื่อคุณเริ่มเข้าใจคำตอบของคำถามเหล่านี้ทั้งหมดแล้ว คุณจะสามารถเขียนโค้ดที่ผู้อื่นสามารถเข้าใจได้

ที่กล่าวว่าฉันต้องการเตือนคุณเกี่ยวกับการวิเคราะห์รหัสในวิธีการของ Java SDK วิธีการหลายอย่างถูกเขียนขึ้นใหม่เพื่อเพิ่มความเร็วสูงสุด และความสามารถในการอ่านก็เป็นเรื่องที่น่าสงสัย

แยกโปรแกรมออกเป็นส่วนตรรกะอย่างถูกต้อง

เกือบทุกโปรแกรมแบ่งออกเป็นส่วนหรือโมดูล แต่ละส่วนมีหน้าที่รับผิดชอบในแง่มุมของโปรแกรม

คอมพิวเตอร์มีเมนบอร์ด จอภาพ และแป้นพิมพ์ ทั้งหมดนี้เป็นชิ้นส่วนที่แยกจากกันและประกอบกันอย่างหลวมๆ ยิ่งไปกว่านั้น พวกมันโต้ตอบในรูปแบบที่เป็นมาตรฐาน: USB, HDMI ฯลฯ หากคุณทำกาแฟหกใส่คีย์บอร์ด คุณสามารถล้างมันออกในอ่าง ปล่อยให้แห้ง แล้วใช้งานต่อ

แต่แล็ปท็อปเป็นตัวอย่างของสถาปัตยกรรมแบบเสาหิน: ดูเหมือนว่าเราจะแยกแยะส่วนตรรกะที่แยกจากกัน แต่พวกมันจะรวมเข้าด้วยกันมากกว่า ใน MacBookPro คุณต้องถอดแล็ปท็อปออกครึ่งหนึ่งเพื่อทำความสะอาดแป้นพิมพ์ และการทำกาแฟหกใส่แล็ปท็อปคือเหตุผลที่ควรสั่งซื้อแล็ปท็อปเครื่องใหม่ ไม่ใช่กาแฟแก้วใหม่


3. การสร้างชั้นเรียนของคุณเอง

แต่เนื่องจากคุณเพิ่งเรียนรู้การเขียนโปรแกรม คุณควรเริ่มต้นเล็กๆ ด้วยการเรียนรู้การสร้างชั้นเรียนของคุณเอง

แน่นอน คุณได้สร้างคลาสแล้ว แต่คุณต้องเรียนรู้เพื่อทำความเข้าใจว่าคลาสใดควรรวมไว้ในโปรแกรม ตั้งชื่อคลาสอย่างไร และควรมีเมธอดใด และควรมีปฏิสัมพันธ์กันอย่างไร

รายชื่อหน่วยงาน

ถ้าไม่รู้จะเริ่มตรงไหน ให้เริ่มจากจุดเริ่มต้น

เมื่อคุณเริ่มออกแบบโปรแกรมเป็นครั้งแรก คุณสามารถหยิบกระดาษขึ้นมาแล้วจดรายการเอนทิตี (วัตถุ) ที่ควรอยู่ในโปรแกรม แล้วจึงเขียนโค้ดตามหลักการว่าแต่ละเอนทิตีเป็นคลาสที่แยกจากกัน

ตัวอย่าง

สมมติว่าคุณต้องการเขียนเกมหมากรุก คุณจะต้องมีเอนทิตีต่อไปนี้: กระดานหมากรุกและตัวหมากรุก 6 ประเภท ชิ้นส่วนเคลื่อนที่ในรูปแบบต่างๆ และมีค่าต่างกัน มันสมเหตุสมผลแล้วที่พวกเขาเป็นชั้นเรียนที่แยกจากกัน เมื่อคุณเริ่มเรียนครั้งแรก ยิ่งมีคลาสมากเท่าไหร่ก็ยิ่งดีเท่านั้น

เป็นเรื่องยากมากที่จะพบโปรแกรมเมอร์มือใหม่ที่เขียนสิบคลาสแทนที่จะเป็นสองคลาส แทนที่จะเขียน 10 คลาส ผู้เริ่มต้นชอบเขียน 2 คลาสหรืออาจแค่ 1 คลาส ดังนั้นโปรดเขียนคลาสเพิ่มเติม เพื่อนโปรแกรมเมอร์ของฉัน และโค้ดของคุณจะชัดเจนขึ้นสำหรับทุกคน ยกเว้นบางทีคุณ 😛

หมากรุก

สมมติว่าเราตัดสินใจเขียนคลาสสำหรับหมากรุก: คลาสเหล่านี้จะเป็นอย่างไร

กระดานหมากรุกเป็นเพียงอาร์เรย์ 8 คูณ 8 หรือไม่ เป็นการดีกว่าที่จะสร้างคลาสแยกต่างหากที่เก็บการอ้างอิงถึงอาร์เรย์ไว้ภายใน จากนั้นคุณสามารถเพิ่มเมธอดที่มีประโยชน์มากมายให้กับคลาส "กระดานหมากรุก" เช่น เพื่อตรวจสอบว่าเซลล์ใดเซลล์หนึ่งว่างหรือว่างอยู่

โดยทั่วไป เมื่อคุณเริ่มต้น ให้ปฏิบัติตามหลักการนี้เสมอ: โปรแกรมมีเอนทิตีที่หลากหลาย และเอนทิตีมีประเภท ประเภทนี้คือคลาส


4. ตัวแปรคงที่และวิธีการ

อย่าลืมใช้ตัวแปรและเมธอดแบบสแตติกด้วย หากคุณมีหมากรุกหนึ่งตัวโต้ตอบกับอีกตัวบนกระดานหมากรุก โค้ดของคุณต้องการวิธีการที่อ้างอิงถึงตัวหมากรุกตัวแรกและตัวที่สองเช่นเดียวกับกระดานหมากรุก

ตัวแปรแบบสแตติกซึ่งสามารถเข้าถึงได้จากทุกที่ในโปรแกรม โดยทั่วไปจะใช้เพื่อหลีกเลี่ยงการส่งผ่านการอ้างอิงไปยังวัตถุที่ "มีอยู่เสมอ"

ตัวอย่างเช่น:

รหัส บันทึก
public class ChessBoard
{
   public static ChessBoard board = new ChessBoard();
   public ChessItem[][] cells = new ChessItem[8][8];
   ...
}

public class Game
{
   public static void main(String[] args)
   {
      var board = ChessBoard.board;
      board.cells[0][3] = new King(Color.WHITE);
      board.cells[0][4] = new Queen(Color.WHITE);
      ...
   }
}


การอ้างอิงถึงChessBoardวัตถุ เดียว
อาร์เรย์สองมิติขนาด 8x8 ไม่ใช่ตัวแปรคงที่








เพิ่มชิ้นส่วนลงในกระดาน

หรือแทนที่จะใช้ตัวแปรสแตติก คุณสามารถสร้างเมธอดที่ส่งคืนอ็อบเจกต์ singleton ตัวอย่างเช่น:

public class ChessBoard
{
   private static ChessBoard board = new ChessBoard();
   public static ChessBoard getBoard()
   {
      return board;
   }

   public ChessItem[][] cells = new ChessItem[8][8];
   ...
}

public class Game
{
   public static void main(String[] args)
   {
      var board = ChessBoard.getBoard();
      board.cells[0][3] = new King(Color.WHITE);
      board.cells[0][4] = new Queen(Color.WHITE);
      ...
   }
}