2012-01-27 15 views
11

lớp Parent của tôi là:thừa kế, phương pháp chữ ký, phương pháp trọng và ném khoản

import java.io.IOException; 
public class Parent { 
     int x = 0; 
     public int getX() throws IOException{ 
     if(x<=0){ 
     throw new IOException(); 
     } 
     return x; 
     } 
} 

tôi extend lớp này để viết một lớp con Child:

public class Child1 extends Parent{ 
    public int getX(){ 
     return x+10; 
    } 
} 

Thông báo khi trọng các GetX Phương pháp trong lớp Child, tôi đã xóa mệnh đề throws khỏi định nghĩa phương thức .Làm như vậy kết quả trong một hành vi bất thường của trình biên dịch được mong đợi:

new Parent().getX() ; 

không biên dịch mà không kèm theo nó trong khối try-catch, như mong đợi.

new Child().getX() ; 

biên dịch mà không kèm theo nó trong khối try-catch.

Nhưng các dòng mã dưới đây cần khối try-catch.

Parent p = new Child(); 
p.getX(); 

Vì đây có thể được dự kiến ​​tức là sử dụng một tài liệu tham khảo lớp cha để gọi một phương pháp trẻ trong thời gian chạy đa hình, tại sao các nhà thiết kế của Java đã không làm cho nó bắt buộc phải bao gồm ném khoản trong định nghĩa phương pháp trong khi ghi đè một phương thức lớp cha cụ thể? Tôi có nghĩa là nếu một phương thức lớp cha đã ném mệnh đề trong định nghĩa của nó, thì khi ghi đè nó thì phương thức ghi đè cũng nên bao gồm mệnh đề ném, phải không?

+0

Trong câu cuối cùng của bạn, ý của bạn là ", sau đó khi ghi đè phương thức *** ghi đè (phương thức trong phân lớp) cũng phải bao gồm mệnh đề ném" ??? – Bhushan

Trả lời

25

Không, điều này là thích hợp - một phương pháp ghi đè có thể hạn chế hơn về những gì nó ném (và trả về) vì điều này có thể hữu ích cho người gọi biết tại thời gian biên dịch họ sẽ sử dụng phương pháp ghi đè và không muốn làm phiền với các ngoại lệ không thể xảy ra được. Tuy nhiên, nó phải hạn chế hơn là cho phép, để người dùng không thể làm bất ngờ người làm truy cập thông qua khai báo gốc.

Sử dụng phương pháp ghi đè thông qua tham chiếu loại Parent sẽ không bao giờ vi phạm hợp đồng "có thể ném IOException" - việc không có ngoại lệ không vi phạm hợp đồng. Cách khác vòng (nếu phụ huynh không khai báo ngoại lệ, nhưng phương pháp ghi đè) sẽ là vi phạm hợp đồng.

+0

Cảm ơn vì đã khai sáng cho tôi :) – NINCOMPOOP

+0

bạn có thể chấp nhận câu trả lời của Jon rồi :) – Bhushan

+0

'để nó không thể làm người gọi bất ngờ truy cập thông qua khai báo của cha mẹ'. Điều này thực sự giúp tôi hiểu được lý do. –

3

Vâng, phương pháp ghi đè có thể không ném bất kỳ ngoại lệ nào (hoặc ít nhất ít ngoại lệ), do đó bạn có thể loại bỏ ngoại lệ khỏi mệnh đề ném (hoặc toàn bộ mệnh đề ném).

Giả sử phương thức ghi đè bắt tất cả ngoại lệ, ghi nhật ký chúng và trả về một giá trị đặc biệt. Mặc dù đó không phải là phong cách tốt (nó sẽ thay đổi ngữ nghĩa của phương thức) nhưng nó vẫn có thể và do đó bạn không cần phải nắm bắt các ngoại lệ không bao giờ bị ném nếu bạn biết tại thời gian biên dịch mà bạn đang xử lý với Child.

Thêm ngoại lệ sẽ không hoạt động vì người dùng của lớp truy cập thông qua tham chiếu Parent không biết bất kỳ ngoại lệ nào mà Child có thể thêm.

2

Bạn có quyền tự do ghi đè phương thức mà không có từ khóa ném, vì nếu bạn muốn phát triển phương pháp bằng cách kiểm soát tất cả ngoại lệ, bạn có thể thực hiện điều đó bằng cách ghi đè phương thức mà không cần bất kỳ điều khoản ném nào. Nhưng hãy nhớ một điều rằng nếu bạn muốn bao gồm mệnh đề ném trong phương thức lớp con, thì mệnh đề ném phải liên kết với ngoại lệ phải là cùng một hoặc lớp con của ngoại lệ được ném bởi phương thức siêu lớp của nó. ví dụ-

class Super{ 
    void a()throws IOException{ 
     ...... 
    } 
} 
class Sub extends Super{ 
    void a()throws IOException{ 
     ...... 
    } 
} 

Phương thức a() của lớp Sub phải ném IOException hoặc bất kỳ lớp con nào của IOException, nếu không trình biên dịch sẽ hiển thị lỗi.

Điều đó có nghĩa nếu bạn viết

void a()throws Exception 

trong Sub lớp, sau đó nó sẽ gây ra lỗi biên dịch.

2

Dễ nhớ

  1. Tiếp cận modifier có thể được thay đổi từ hạn chế để ít hạn chế,
    ví dụ từ bảo vệ cho công chúng, nhưng không phải ngược lại
  2. ném chữ ký có thể thay đổi từ ngoại lệ cha mẹ sang con lớp ngoại lệ, nhưng không ngược lại

mã này là hợp lệ

public class A { 

    protected String foo() throws Exception{ 
     return "a"; 
    } 

    class B extends A { 
     @Override 
     public String foo() throws IOException{ 
      return "b"; 
     } 
    } 
} 

phương pháp foo Overrided có quyền truy cập công cộng, không được bảo vệ và throws IOException rằng con của Exception

Mã này là không hợp lệ

public class A { 

    public String foo() throws IOException{ 
     return "a"; 
    } 

    class B extends A { 
     @Override 
     protected String foo() throws Exception{ 
      return "b"; 
     } 
    } 
} 

phương pháp foo Overrided có sửa đổi lần truy cập hạn chế hơn và throws Exception mà KHÔNG trẻ của IOException

bởi theo cách bạn có thể ghi đè phương pháp từ lớp cha và không ném ecxeptions ở tất cả

c này ode hợp lệ

public class A { 

    public String foo() throws IOException{ 
     return "a"; 
    } 

    class B extends A { 
     @Override 
     public String foo(){ 
      return "b"; 
     } 
    } 
} 
+0

Điều này giúp, bị hủy trong cuộc phỏng vấn vì câu hỏi này. – saiki4116