2016-02-03 20 views
5

Tôi không thể tìm thấy câu hỏi như tôi, vì vậy tôi hy vọng nó không phải là một bản sao.Java - Ẩn Ghi đè và sửa đổi cuối cùng

Một lần nữa nó về trọng và ẩn. Tôi nghĩ - nhưng tôi có thể sai - tôi hiểu cả hai.

Mã sau hoạt động như mong đợi, cả hai phương pháp đều bị ẩn. method1 bởi vì nó là một phương thức riêng và các phương thức riêng không thể bị ghi đè chỉ bị ẩn, method2 bởi vì nó là phương thức tĩnh và tĩnh không thể bị ghi đè, chúng chỉ có thể được ẩn đi.

public class Child extends Parent { 
    public void method1(){System.out.println("child");}  
    public static void method2(){ System.out.println("static child");} 
} 

class Parent{ 
    private void method1(){ System.out.println("parent");}  
    public static void method2(){ System.out.println("static parent");} 

    public static void main(String[] args){ 
      Parent p = new Child(); 
      p.method1(); //prints out "parent" 
      p.method2(); //prints out "static parent" 
    } 
} 

Nếu tôi đọc specs nó nói:

http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.3.3

Một phương pháp có thể được tuyên bố chính thức để ngăn chặn các lớp con từ trọng hoặc che giấu nó.

Nếu tôi thay đổi method1 trong lớp cha để "cuối cùng"

private final void method1(){ System.out.println("parent");} 

Tất cả mọi thứ hoạt động tốt. chỉnh sửa bắt đầu: Tôi mong đợi một lỗi trình biên dịch nói rằng phương pháp cuối cùng không thể được ẩn, nhưng điều đó đã không xảy ra. : chỉnh sửa kết thúc

Câu hỏi số 1: điều đó có nghĩa là chỉ có phương pháp tĩnh có thể bị ẩn? Trong cuốn sách tôi đang đọc (hướng dẫn nghiên cứu OCA, Jeanne Boyarsky và trang Scott Selikoff 252), họ nói rõ ràng rằng một phương pháp riêng đã bị ẩn.

Sau đó, tôi đã thay đổi method2 trong lớp cha để

public final static void method2(){ System.out.println("static parent");} 

Bây giờ trình biên dịch không phàn nàn, các lỗi nói: "Trẻ em không thể ghi đè method2()", mà là khá khó hiểu bởi vì tôi nghĩ rằng tôi đã cố gắng để che giấu một phương pháp .

Câu hỏi số 2: Không phải là "Trẻ em không thể ẩn phương thức 2()"?

chỉnh sửa bắt đầu: Tôi biết rằng không có ghi đè nào xảy ra ở đây, nhưng như thông số được đề cập chỉ ra: sửa đổi cuối cùng ngăn các phương thức bị ghi đè hoặc ẩn, đó là lý do tôi đặt nó vào tiêu đề. : chỉnh sửa cuối

+0

Ví dụ của bạn hơi khó hiểu vì phương thức 2 được xác định trước phương thức1. Để dễ đọc, bạn có thể muốn cấu trúc lại thành: a) đầu tiên định nghĩa method1, sau đó metho2 và b) đầu tiên xác định lớp Parent, sau đó lớp Child và cuối cùng là một lớp public chứa phương thức main như là một khung kiểm thử. – penguineer

+0

Và bây giờ câu hỏi thực sự của tôi: Bạn có ý nghĩa gì bởi "Mọi thứ hoạt động tốt"? Vui lòng nêu rõ những gì bạn mong đợi và điều gì sẽ xảy ra. Tôi sẽ mong đợi một lỗi trình biên dịch khi Overriding một phương pháp cuối cùng - bạn đã nhận được lỗi đó? Hoặc đã làm các trình biên dịch đi qua với nó? Bạn có thấy bản in của phương pháp overriden không? – penguineer

+0

Hướng dẫn Oracle ngụ ý rằng bạn không thể ghi đè phương thức 'tĩnh', chỉ ẩn nó: https://docs.oracle.com/javase/tutorial/java/IandI/override.html –

Trả lời

8

Câu hỏi 1

Câu hỏi số 1: Điều đó có nghĩa chỉ phương pháp tĩnh có thể được ẩn?

Parent.method1() là không hiển thị trong cũng không được thừa hưởng bởi Child chỉ đơn giản nhờ là private. Vì vậy, Child.method1() không ghi đè hoặc ẩn Parent.method1(), nó chỉ tạo một phương thức mới trong Child có cùng tên, thông số và kiểu trả về.

Xem http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.3:

Lưu ý rằng một phương pháp riêng không thể ẩn hoặc ghi đè theo nghĩa kỹ thuật của những điều khoản.Điều này có nghĩa là một phân lớp có thể khai báo một phương thức có cùng chữ ký như một phương thức riêng trong một trong các siêu lớp của nó, và không yêu cầu rằng kiểu trả về hoặc mệnh đề ném của phương thức như vậy có bất kỳ mối quan hệ nào với phương thức riêng tư trong siêu lớp.

Câu hỏi 2

Câu hỏi số 2: Không nên đó là "trẻ em không thể che giấu method2()"?

Có, bạn là chính xác. Nó phải là "ẩn". Mỗi JLS (http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.2),

Nếu một lớp C tuyên bố hoặc được thừa hưởng một phương pháp m tĩnh, sau đó m được cho là ẩn bất kỳ phương pháp m', nơi mà các chữ ký của m là một subsignature (§8.4.2) chữ ký của m', trong superclasses và superinterfaces của C mà nếu không sẽ có thể truy cập tới mã trong C.

'Ẩn' là những gì static phương pháp làm để static phương pháp. "Overriding" là các phương thức instance làm gì với các phương thức instance. Không thể trộn lẫn hai phương thức: phương thức static không thể ghi đè hoặc ẩn phương thức thể hiện và phương pháp thể hiện không thể ghi đè hoặc ẩn phương thức static.

BTW, trình biên dịch Eclipse của tôi đưa ra một thông báo lỗi tương tự: "Không thể ghi đè lên các phương pháp cuối cùng từ Parent"

+0

phương pháp riêng và ẩn: Tôi đọc điều này trong cuốn sách đã nói, rằng một phương thức riêng đã bị ẩn và vì hành vi của trình biên dịch tôi nghĩ nó không thể ẩn được (vì các thông số về sửa đổi cuối cùng và phương thức ẩn). Tôi đã không tìm thấy phần (8.4.8.3) về phương pháp riêng tư mặc dù. Cảm ơn, điều đó làm sáng tỏ toàn bộ sự việc. – whoCares

+0

P.S. Trình biên dịch Eclipse: Tôi biết, tôi đã thử nghiệm toàn bộ điều trong giao diện điều khiển và nhật thực. Lỗi tương tự. – whoCares

2

Vâng, tôi khá mới để java, nhưng tôi sẽ cố gắng trả lời.

Sự khác biệt nằm trong thực tế là bạn đang sử dụng từ bổ nghĩa cấp độ truy cập khác nhau: bạn đang sử dụng riêng trên method1() của lớp phụ huynh và cộng đồng về method1() trên lớp trẻ em. Trong thực tế, bạn không ẩn phương pháp vì nó không phải là phương pháp tương tự. Công cụ sửa đổi riêng chỉ định rằng thành viên chỉ có thể được truy cập trong lớp riêng của nó, do đó, bạn đang sử dụng một phương thức mới khi bạn khai báo method1() trên lớp Con. Mặc dù, trẻ thừa hưởng tất cả các phương thức từ Parent (vì nó mở rộng nó), các phương thức riêng không được kế thừa. Trong trường hợp của method2(), vì nó được khai báo là public, nó được kế thừa bởi lớp Con và có thể bị ẩn.

Thông tin thêm về nó (Trích từ oracle tutorials):

cá nhân thành viên trong một lớp cha

Một lớp con không kế thừa các thành viên private của lớp cha của nó. Tuy nhiên, nếu lớp cha có các phương thức công khai hoặc được bảo vệ để truy cập các trường riêng của nó, thì các lớp này cũng có thể được sử dụng bởi lớp con.

Lớp lồng nhau có quyền truy cập vào tất cả các thành viên riêng tư của lớp kèm theo — cả trường và phương thức. Do đó, một lớp lồng nhau công cộng hoặc được bảo vệ được thừa kế bởi một lớp con có quyền truy cập gián tiếp vào tất cả các thành viên riêng của lớp cha.

EDITED: Câu hỏi 2:

Bạn giấu một phương pháp tĩnh, không phải là một trận chung kết.Chỉ những người tĩnh mới có thể được ẩn như ở đây:

class SuperClass { 
    static void display() { 
     System.out.println("Super"); 
    } 
} 

class SubClass extends SuperClass { 
    static void display() { 
     System.out.println("Sub"); 
    } 
} 

public class Test { 
    public static void main(String[] args) { 
     // Prints "Super" in console 
     SuperClass sup = new SubClass(); 
     sup.display(); 

     // Prints "Sub" in console 
     SubClass sub = new SubClass(); 
     sub.display(); 
    } 
} 

Bạn sử dụng từ khóa cuối cùng trong khai báo phương pháp để chỉ ra rằng phương pháp không thể bị ghi đè bởi lớp con. Vì vậy, nếu bạn thay đổi nó, bạn đang ghi đè nó và, do đó, trình biên dịch nói:

overridden method is static,final (thông báo final).

Trình biên dịch than phiền về nó vì bạn không còn ẩn nó nữa. Khi bạn khai báo nó final, bạn sẽ ghi đè nó. Nó sẽ cung cấp cho bạn cùng một lỗi, nếu bạn không sử dụng công cụ sửa đổi static trên lớp Trẻ em vì bạn sẽ cố gắng ghi đè những gì không còn là static. Ẩn chỉ được sử dụng khi phương thức tĩnh ẩn một phương thức tĩnh khác. Nếu bạn thử:

  1. phương pháp phi tĩnh "giấu" giá trị tĩnh: ghi đè lên.
  2. phương thức cuối cùng "ẩn" tĩnh: đó là ghi đè.

Trong những trường hợp đó, bạn không phải cố gắng ẩn nữa (vì ẩn chỉ được sử dụng trên tĩnh) nhưng bạn đang cố gắng ghi đè.

+0

Chính xác. Tôi đã nói về trình biên dịch, mặc dù. Nếu bạn thử: phương thức instance "ẩn" một static, trình complier sẽ nghĩ rằng bạn đang cố gắng ghi đè nó bởi vì bạn chỉ có thể ẩn các phương thức tĩnh. Đó là lý do tại sao trình biên dịch không nói phương pháp được ẩn là tĩnh, cuối cùng. Bạn thấy đấy, trình biên dịch chỉ biết rằng tĩnh có thể ẩn tĩnh. Nếu bạn cố gắng thay đổi tĩnh theo bất kỳ cách nào khác ngoài tĩnh ẩn, trình biên dịch sẽ nghĩ bạn đang ghi đè nó. Không có phương thức nào là tĩnh, lỗi cuối cùng vì việc ẩn chỉ xảy ra trên ngữ cảnh tĩnh, theo như tôi nghĩ. :) – ClauCece

+0

Ồ, tệ của tôi. Tôi đang nói một cách giả định. Tôi đã nói: Giả sử rằng, bạn giả sử rằng bạn viết: phương pháp dụ "giấu" một tĩnh. Cảm ơn :) – ClauCece

Các vấn đề liên quan