Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

Parent-Child Hierarchy สำคัญไหมกับ Throws ขณะ Overriding ใน Java?

สำคัญมาก กฎ Exception ใน Overriding คล้ายกับ Try-Catch: Subclass เมธอดอาจโยน Exception ชนิดเดียวกัน หรือ Subtype (ลูก) เท่านั้น ห้ามโยน Supertype (พ่อแม่)

กฎหลัก (Overriding & Throws)

  1. Override เมธอดที่โยน Checked Exception -> โยน Exception ชนิดเดียวกัน ได้
  2. โยน Exception ที่เป็น Subclass (Subtype) ของ Exception เดิม ได้
  3. ห้ามโยน Supertype (Parent Class) ของ Exception เดิม
  4. Override โดย ไม่โยน Exception เลย ก็ได้

ตัวอย่าง: โยน Subtype (ถูกต้อง)

class Demo {
    public void sample() throws ArrayIndexOutOfBoundsException {
        System.out.println("Demo class");
    }
}

class SuperTest extends Demo {
    // IndexOutOfBoundsException เป็น Parent ของ ArrayIndexOutOfBoundsException -> ผิด!
    // แต่อยู่ใน Hierarchy เดียวกัน ลองดูตัวอย่างถูกต้องด้านล่าง
    public void sample() throws IndexOutOfBoundsException { // Error: Supertype
        System.out.println("SuperTest class");
    }
}

ตัวอย่างข้างต้น ผิด เพราะ IndexOutOfBoundsException เป็น Supertype ของ ArrayIndexOutOfBoundsException

ตัวอย่างที่ถูกต้อง: โยน Subtype

import java.io.IOException;
import java.io.EOFException; // EOFException extends IOException

class Demo {
    public void sample() throws IOException {
        System.out.println("Demo class throws IOException");
    }
}

class SuperTest extends Demo {
    // EOFException เป็น Subtype ของ IOException -> ถูกต้อง
    public void sample() throws EOFException {
        System.out.println("SuperTest throws EOFException (subtype)");
    }
}

public class Test {
    public static void main(String args[]) {
        Demo obj = new SuperTest();
        try {
            obj.sample();
        } catch (IOException ex) { // จับ IOException ได้ (Parent)
            System.out.println("Caught IOException");
        }
    }
}

ผลลัพธ์

SuperTest throws EOFException (subtype)
Caught IOException

ตัวอย่างที่ Error: โยน Supertype

class Demo {
    public void sample() throws EOFException { // Specific
        System.out.println("Demo throws EOFException");
    }
}

class SuperTest extends Demo {
    // IOException เป็น Supertype ของ EOFException -> Error!
    public void sample() throws IOException {
        System.out.println("SuperTest throws IOException");
    }
}

Compile Error

Test.java:12: error: sample() in SuperTest cannot override sample() in Demo
    public void sample() throws IOException {
                                    ^
  overridden method does not throw IOException

เหตุผล

Code เรียกผ่าน Demo obj = new SuperTest() คาดหวังแค่ EOFException แต่ Subclass โยน IOException ที่กว้างกว่า -> Caller ไม่ Catch ได้ -> Runtime Crash Java จึงบังคับที่ Compile-time

สรุป

Hierarchy ของ Exception สำคัญมาก: Override ได้แค่ Same หรือ Narrower (Subtype) เท่านั้น สอดคล้องกับ Liskov Substitution Principle