[JAVA] Abstract คือ อะไร และต่างกับ Interface อย่างไร

หลายๆคนคงสงสัยว่า Keyword Abstract มัน คือ อะไร และเมื่อไหร่ที่ควรจะใช้ วันนี้ผมมีตัวอย่างง่ายๆในการอธิบายนะครับ โดยอาจจะแทรกเนื้อหาเกี่ยวกับ interface เพิ่มเข้าไปด้วยครับ เพราะลายคนสับสนกันเยอะ  โดยผมขอเริ่มโจทย์ที่เราต้องใช้ Abstract Class ดังนี้

จงเขียน class Student ซึ่งประกอบด้วย data members ดังนี้ name (ชื่อนิสิต), test (อะเรย์ของคะแนน), NUM_OF_TESTS (ค่าคงที่เป็นจำนวนของ test) และ courseGrade (เกรดของวิชา) ให้สร้าง Constructor, methods get/set และ abstract method computeCourseGrade โดยมีวิธีการคำนวณต่างกันไปสำหรับนิสิตปริญญาตรี (UndergraduateStudent) และบัณฑิตศึกษา (GraduateStudent)ให้เขียน class UndergraduateStudent ซึ่งเป็น subclass ของ Student และ ทำการ implement method computeCourseGrade ตามเกณฑ์ต่อไปนี้คือ ถ้าคะแนนเฉลี่ย >= 70 ผ่าน (Pass) ถ้าคะแนนเฉลี่ย < 70 ไม่ผ่าน (Fail)

ก่อนที่จะทำโจทย์ ผมอยากให้รู้จักคำศัพท์บางตัวก่อน

  • Signature ของ Method คือ อะไร
    • การกำหนดลักษณะของ Method name(ชื่อ method) + Parameter List(ตัวแปรที่จะส่งเข้าไป)
      1
  • Method Header คือ อะไร
    • พูดง่ายๆ คือ Signature หรือการประกาศ Method ว่ามีซื่ออะไร รับอะไรมาบ้าง ส่วน Logic การทำงานของมันจะไปอยู่ใน Method Detail จ้า ดูตามรูปเลย จะมี pattern ตามนี้ครับ
      2
  • Interface คือ อะไร
    • Interface คือ Class คือ ที่มีข้อมีเฉพาะตัว Method header เท่านั้น ไม่มีการ implement การทำงานอะไรเลย
    • Interface ในแง่ของ OOP เป็น Real Abstract อธิบายง่ายๆเลย คือ มันไม่มี Logic การทำงานอะไรเลย มาเป็นกรอบคร่าวๆ
    • เวลาสร้าง Class ต้องบอกด้วย keyword interface เสมอ ดังตัวอย่างต่อไปนี้
      public interface ListADT{
          //Has only Method Header
          public void insert(Object e) throws Exception;
          public Object retrieve() throws Exception;
      }
    • Class ที่จะเอา interface ไปใช้งานนั้น ต้องใช้ keyword implements เสมอ ดังตัวอย่างต่อไปนี้
      public class SimpleList implements ListADT{
          //some code here !!
      }
  • Abstract คือ อะไร
    • เหมือนกับ Interface แต่จะมีข้อกำหนดที่ยืดหยุ่นกว่า เพราะ เราสามารถที่่ใส่ Logic  (เพิ่ม Method และการทำงาน) implement เข้าไปใน Class ที่เป็น abstract ได้
    • เวลาสร้าง Class จะต้องบอกไว้ด้วย keyword abstract
    • Method ไหนที่ต้องการให้ SubClass เอาไป Implememt ต่อ ต้องมี Keyword abstract ระบุ เพื่อไว้ในส่วนของ Method Modifier เสมอ ดังตัวอย่างต่อไปนี้
      public abstract class Student{
          //Has Method Header
          public abstract void computeCourseGrade(); //มีการใส่ Keyword abstract กำกับไว้
          //Implement Method
          public String getCourseGrade(){
      	return courseGrade;
          }
      }
      
    • Class ที่จะเอา abstract ไปใช้งานนั้น จะต้องใช้ keyword extends ดังตัวอย่างต่อไปนี้
      public class UndergraduateStudent extends Student {
          //some code here !!
      }
      
  • เมื่อไหรควรใช้ Interface หรือควรใช้ Abstract ?
    • ใช้ Interface Class เมื่อต้องการวางกรอบ ขอบเขคร่าวๆ เพื่อใช้ subclass เอาทำ implement การทำงานภายในต่อได้เอง
    • ใช้ Abstract Class เมื่อรู้ว่ามีการทำงานบางอย่างที่ ซ้ำๆกันใน subclass โดยยกขึ้นมาเขียนใน Abstract Class เลย และยังเป็นการทำ template ป้องกัน fragment จากการที่ DEV ไป implement กันเอง เพราะต่างคนต่าง Logic แล้วภายหลังจะ maintain ลำบาก
      • ตัวอย่างการใช้ Abstract Class ถ้าลองจาก Java doc เช่น Abstract Class java.util.AbstractMap ที่รวบรวมการทำงานที่้เหมือนกันของ Subclass ต่างๆ ได้แก่ java.util.EnumMap ,java.util.HashMap ,java.util.LinkedHashMap ,java.util.IdentityHashMap และ java.util.TreeMap โดยสามารถเข้าไปดูใน Javadoc หรือ ดูจากรูปได้ ดังนี้
        4
  • สุดท้ายก่อนจะลง Code ควรวางแผน Design ระบบให้ดีก่อนนะครับ ^___^

เฉลยโจทย์กันก่อน อธิบายยาวจนลืม

  • ก่อนอื่นเลยมาดู Diagram แสดงความสัมพันธ์ระหว่าง Class Student ซึ่งเป็น Abstract Class และ Class UndergraduateStudent กับ Class GraduateStudent เป็น SubClass ดังรูป
    3
  • มาลองเขียน Class Student ตามที่เงื่อนไขที่โจทย์กำหนดเลยครับ
    public abstract class Student{
        protected final static int NUM_OF_TEST = 3;
        protected String name;
        protected String courseGrade;
        public Student(){
            this("No Name");
        }
        public Student(String studentName){
            name = studentName;
            test = new int[NUM_OF_TEST];
            courseGrade = "";
        }
        public abstract void computeCourseGrade();
        public String getCourseGrade(){
            return courseGrade;
        }
        public String getName(){
            return name;
        }
        public int getTestScore(int testNumber){
            return test[testNumber - 1];
        }
        public void setName(String newName){
            name = newName;
        }
        public void setTestScore(int testNumber,int testScore){
            test[testNumber - 1] = testScore;
        }
    }
    
  • มาลองเขียน Class UndergraduateStudent ตามที่เงื่อนไขที่โจทย์กำหนดเลยครับ
    public class UndergraduateStudent extends Student {
        public UndergraduateStudent(){
            super("No Name");
        }
        public void computeCourseGrade(){
            int total = 0;
            for(int i = 0;i < NUM_OF_TEST; i++){
                total += test[i]; 
            } 
            if(total / NUM_OF_TEST >= 70){
                courseGrade = "Pass";
            }else{
                courseGrade = "No Pass";
            }
        }
    }
    
  • ส่วน Class GraduateStudent ผมจะไม่เฉลยนะครับ ลองไปอ่านดูดีๆ จะพบวา่โจทย์ไม่ได้สั่ง แต่ถ้าผู้อ่านลองเขียนเองสามารถนำ Class UndergraduateStudent ไปประยุกต์ใช้ โดยปรับเปลี่ยนเงื่อนไขให้แตกต่างกัน เช่น ถ้าคะแนนเฉลี่ย >= 90 ผ่าน (Pass) ถ้าคะแนนเฉลี่ย < 90 ไม่ผ่าน (Fail) เป็นต้น

Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.