2012-10-26 10 views
9

Tôi nhầm lẫn về phương pháp nhân bản ghi đè trong lớp mà tôi muốn đối tượng nhân bản vô tính.Tại sao phải ghi đè lên phương thức sao chép trong Java

lớp Object đã bảo vệ đối tượng phương pháp và theo những hành vi bảo vệ đó là Khi một phương pháp được bảo vệ, nó chỉ có thể được truy cập bởi các lớp đó, lớp con của lớp, hoặc các lớp trong gói giống như lớp.

Vì mọi lớp trong Java kéo dài từ đối tượng, do đó, nó phải có phương pháp sao chép nhưng chúng tôi vẫn buộc phải ghi đè lên bản sao. Tại sao nó được yêu cầu?

Ngoài ra, tôi đã đọc tại một số địa điểm để ghi đè đối tượng nhân bản và công khai đối tượng đó. Tôi tự hỏi, tại sao nó như vậy?

Tất cả câu trả lời đều được chào đón.

+0

C chi tiết razy trên bản sao - http://stackoverflow.com/questions/1138769/why-is-the-clone-method-protected-in-java-lang-object –

Trả lời

8

Như mọi tầng lớp trong Java kéo dài từ Object, vì vậy nó cần phải có phương pháp nhân bản nhưng chúng tôi vẫn đang buộc phải ghi đè lên bản sao

Không bạn không buộc phải ghi đè lên các phương pháp clone. Trong thừa kế, khi bạn kế thừa một lớp, bạn không bị buộc phải ghi đè lên phương thức của nó. Công cụ sửa đổi của nó là công khai hoặc được bảo vệ không tạo ra nhiều sự khác biệt. Tuy nhiên, nếu bạn muốn gọi phương thức trực tiếp trên tham chiếu lớp super, thì phương pháp đó phải là public. Các phương thức được bảo vệ chỉ có thể truy cập thông qua kế thừa. Đó là bạn chỉ có thể truy cập chúng thông qua tham chiếu subclass. Hoặc nếu bạn ghi đè phương thức, bạn có thể truy cập chúng thông qua từ khóa super.

Có nói rằng, bạn không nên ghi đè phương pháp clone, vì nó là broken. Bởi vì, đối với một lớp được nhân bản, bạn cần triển khai giao diện Cloneable. Và sau đó, lớp của bạn sử dụng phương thức clone của lớp Object thay thế. Bởi vì, giao diện Cloneable không chính xác có bất kỳ phương thức nào cho cloning. Nó sẽ là một lựa chọn tốt hơn để sử dụng Copy Constructor thay thế.

public class A { 
    private int data; 
    public A() { 
    } 

    public A(A a) { 
     this.data = a.data; 
    } 
} 

Để biết thêm chi tiết, tôi xin đề nghị phải trải qua chương này của Joshua Bloch's Effective Java, trong đó bao gồm tất cả các khía cạnh của việc sử dụng phương pháp clone.

Effective Java- Item # 11 - Override clone judiciously

+0

Như bạn đã viết rằng "Không, bạn không bị buộc phải ghi đè lên phương pháp nhân bản "nhưng tôi không thể gọi bản sao trực tiếp trên đối tượng nếu bản sao không bị ghi đè. Tại sao nó như vậy? – Anand

+0

@anand. Để gọi bất kỳ phương thức 'super class' nào, bạn cần một cá thể của lớp đó. Bây giờ, nếu bạn ghi đè phương thức 'clone', bạn có thể hiện của lớp' Object' là 'super'. Vì vậy, bạn sử dụng 'super.clone()' để gọi nó. –

+0

@anand. Ngoài ra, bạn không thể trực tiếp gọi phương thức 'clone' trên lớp' Object', vì phương thức 'clone' được' bảo vệ' và chỉ có thể truy cập trong 'lớp cơ sở' thông qua' kế thừa'. Vì vậy, bạn có thể gọi nó thông qua cá thể của cùng một lớp. Nhưng lưu ý, bạn cần xử lý 'CloneNotSupportedException' –

4

tôi khuyên bạn nên đọc Effective Java 2nd edition Joshua Bloch. Nó có một chương tốt thảo luận về bản sao.

Tôi sẽ không khuyên bạn thực hiện việc này. Tôi coi đây là lỗi JDK 1.0. Cuốn sách sẽ làm rõ hơn.

tôi khuyên bạn nên viết một constructor sao chép thay vì để có được những gì bạn muốn:

public class Foo { 
    private String name; 
    public Foo(String name) { this.name = name; } 
    public Foo(Foo f) { this.name = f.name; } // copy ctor here. 
} 
+0

Trình tạo bản sao không hoạt động với thừa kế, đó là lý do chúng tôi sao chép –

+1

Không hoạt động? Điều đó giống như thế nào? Tôi cho rằng bản sao không "làm việc" với thừa kế, trừ khi tất cả mọi người trong chuỗi thể hiện sự chăm sóc tuyệt vời. Joshua Bloch không nói những điều tốt đẹp về Cloneable trong "Java hiệu quả". – duffymo

2

Trong nhiều trường hợp nó không phải là rõ ràng những gì một đối tượng nhân bản nên và làm thế nào nó nên cư xử, vì vậy nếu bạn muốn lớp học của bạn để được clonable bạn phải nói như vậy một cách rõ ràng bằng cách ghi đè bản sao và làm cho nó công khai.

Trường hợp bản sao có thể không có ý nghĩa bao gồm các lớp đại diện cho một số tài nguyên, như kết nối mạng hoặc khóa đồng bộ hóa.Nếu các đối tượng này có thể được nhân bản thì không rõ cách sao chép bản sao. Ví dụ, bản sao của kết nối mạng có kết nối TCP/IP của riêng nó hay không bằng cách nào đó sử dụng kết nối hiện có?

0

Sao chép là Protected phương thức trong Object lớp để bạn có thể truy cập vào lớp học bên trong.

Giới thiệu về truy cập- Khi một phương thức được bảo vệ, nó chỉ có thể được truy cập bởi chính lớp đó, các lớp con của lớp, hoặc các lớp trong cùng một gói với lớp đó.

tôi thấy một số quan niệm sai lầm về phương pháp nhân bản

  1. clone() phương pháp là protected bên Object lớp nên bạn không thể gọi clone() ngoài giờ lên lớp. ví dụ. child.clone() trừ khi bạn ghi đè lên nó và làm cho truy cập public
  2. Cloneable là giao diện đánh dấu và nếu bạn không đánh dấu lớp Cloneable sau đó bạn sẽ nhận được CloneNotSupportedException nếu bạn gọi clone() phương pháp
  3. Nếu một lớp chỉ chứa các lĩnh vực nguyên thủy hoặc tham chiếu đến đối tượng bất biến, sau đó thường là trường hợp không có trường nào trong đối tượng được trả về bởi super.clone cần được sửa đổi.
  4. Theo quy ước, đối tượng trả về phải được lấy bằng cách gọi super.clone. Nếu một lớp học và tất cả các lớp học của nó và tất cả các lớp học của nó superclasses (except Object) tuân theo quy ước này, nó sẽ là trường hợp x.clone().getClass() == x.getClass().

Phương pháp chữ ký dưới

@Override 
public Object clone() throws CloneNotSupportedException { 
    return super.clone(); 
} 

Tài liệu tham khảo:

  1. Object#clone()
  2. Cloneable
-1
Why we do override clone() in cloning process? 
    //clone() in Object class is protected 
    package java.lang; 


    protected native Object clone() 
      throws CloneNotSupportedException; 

    java.lang is default import in our java applications. 

Note: If parent and sub class are both in same package then the methods in parent class are directly accessible. If they are in different package,then in subclass we have to override the parent class methods to use. 

    Note:Object class is in java.lang package,we are using it in different package,so we have to override the clone() which is protected in Object class 


first we will look into Protected method behavior.here is sample program to understand this 
    //this class is in com.anusha.clonetrial 
    package com.anusha.clonetrial; 

    public class A { 

     public A() 
     { 

     } 
     protected void disp1() 
     { 
      System.out.println("class a"); 
     } 
     protected void disp2() 
     { 
      System.out.println("class a"); 
     } 
    } 
    //below classes are in com.anusha.Test 
    package com.anusha.Test; 
    import com.anusha.clonetrial.A; 


    class AA { 


     protected void disp1() 
     { 
      System.out.println("class aa"); 
     } 

     protected void disp2() 
     { 
      System.out.println("class aa"); 
     } 
    } 

    //class B derived from AA which is present in the same package 
    class B extends AA 
    { 

     void show() 
     { 


      System.out.println("class b"); 
     } 
    } 

    //class C derived from A which is present in the different package 

    class C extends A 
    { 

     @Override 
     protected void disp1() 
     { 
      super.disp1(); 
     } 
     void show() 
     { 
      System.out.println("class c"); 
     } 
    } 

    package com.anusha.Test; 




    public class CloneTest { 


     public static void main(String[] args) { 
      B b=new B(); 
      C c=new C(); 
      b.disp1(); 
      b.disp2(); 
      c.disp1(); 
      c.disp2();//gives error because it is not overridden. 


     } 

    }