2008-12-30 37 views
5

dùng để chào tất cả,"Dynamic" Đúc trong Java

Tự hỏi nếu có bất kỳ hacker Java người có thể đầu mối cho tôi trong ít tại sao những điều sau đây không làm việc:

public class Parent { 
    public Parent copy() { 
     Parent aCopy = new Parent(); 
     ... 
     return aCopy; 
    } 
} 

public class ChildN extends Parent { 
    ... 
} 

public class Driver { 
    public static void main(String[] args) { 
     ChildN orig = new ChildN(); 
     ... 
     ChildN copy = orig.getClass().cast(orig.copy()); 
    } 
} 

Mã này là khá hạnh phúc để biên dịch, nhưng quyết định ném ClassCastException vào thời gian chạy D =

Chỉnh sửa: Whoah, trả lời rất nhanh. Cảm ơn các bạn! Vì vậy, có vẻ như tôi không thể downcast bằng cách sử dụng phương pháp này ... là có cách nào khác để làm downcasting trong Java? Tôi đã nghĩ về việc có mỗi lớp ChildN ghi đè copy(), nhưng không phải là nhiệt tình về việc thêm mã bản mẫu thêm vào.

+0

Bạn có thể làm điều đó. Hãy xem bản chỉnh sửa của tôi. Tôi mặc dù bạn đã gặp khó khăn trong việc hiểu "đúc" ở vị trí đầu tiên. – OscarRyz

Trả lời

1

(Không thể thêm mã trong nhận xét, vì vậy tôi sẽ thêm tại đây)

Về Cloneable: nếu bạn đang thực hiện Cloneable, hãy thực hiện như sau; sạch hơn nhiều để gọi ...

public class Foo implements Cloneable { 
    public Foo clone() { 
     try { 
      return (Foo) super.clone(); 
     } catch (CloneNotSupportedException e) { 
      return null; // can never happen! 
    } 
} 

[EDIT:. Tôi cũng đã nhìn thấy folks khác sử dụng

throw new AssertionError("This should never happen! I'm Cloneable!"); 

trong khối catch]

+0

Thật vậy, đây là cách tôi đã làm nó! Mặc dù nhận xét của tôi đã được nhiều hơn dọc theo dòng // JAVA EPIC FAIL :) – user50264

6

Dàn diễn viên được hiệu quả cố gắng để làm điều này:

ChildN copy = (ChildN) orig.copy(); 

(Đó là làm việc ra các diễn viên biểu diễn tại thời gian thực hiện, nhưng đó là những gì nó sẽ là vì orig.getClass() sẽ ChildN.class) Tuy nhiên, orig.copy() không trả về một thể hiện của ChildN, nó trả về một cá thể chỉ là Parent, vì vậy nó không thể được chuyển đến ChildN.

4

Nếu ChildN không ghi đè lên bản sao() để trả về một thể hiện của ChildN, sau đó bạn đang cố gắng downCast một đối tượng kiểu cha mẹ để gõ ChildN

9

Cũng giống như cố gắng để làm điều này:

public Object copy(){ 
     return new Object(); 
    } 

và sau đó nỗ lực để:

String s = (String) copy(); 

cha mẹ của bạn lớp và ChildN lớp có mối quan hệ tương tự như ObjectChuỗi

Để làm cho nó làm việc bạn sẽ cần phải làm như sau:

public class ChildN extends Parent { 
    public Parent copy() { 
     return new ChildN(); 
    } 
} 

Đó là, ghi đè lên các phương pháp "sao chép" và trở về bên phải ví dụ.


EDIT

Theo chỉnh sửa của bạn. Đó là thực sự có thể. Đây có thể là một cách có thể:

public class Parent { 
    public Parent copy() { 
     Parent copy = this.getClass().newInstance(); 
     //... 
     return copy; 
    } 
} 

Bằng cách đó bạn không phải ghi đè phương thức "sao chép" trong từng phân lớp. Đây là mẫu thiết kế Prototype.

Tuy nhiên việc sử dụng triển khai này, bạn nên lưu ý hai ngoại lệ đã kiểm tra. Đây là chương trình hoàn chỉnh biên dịch và chạy mà không gặp sự cố.

public class Parent { 
    public Parent copy() throws InstantiationException, IllegalAccessException { 
     Parent copy = this.getClass().newInstance(); 
     //... 
     return copy; 
    } 
} 
class ChildN extends Parent {} 

class Driver { 
    public static void main(String[] args) throws InstantiationException , IllegalAccessException { 
     ChildN orig = new ChildN(); 
     ChildN copy = orig.getClass().cast(orig.copy()); 
     System.out.println("Greetings from : " + copy); 
    } 
} 
+0

Dạy bằng ví dụ! Câu trả lời này là _very_ rõ ràng với tôi. Bây giờ Child.copy cũng có thể được khai báo để trả lại một ChildN iso là Parent? (Tôi biết trong C++ nó có thể) – xtofl

+0

Không có trong Java. Ít nhất không phải trong mã nguồn Java. Để gây nhầm lẫn cho vấn đề hơi * được * cho phép trong mã byte Java ... –

+1

Nó được phép trong mã nguồn trong Java 5+. –

2

java.lang.Class # cast (Object) ném ClassCastException nếu Class # isInstance() trả về false.Từ javadoc cho phương thức đó:

Xác định nếu đối tượng được chỉ định là gán tương ứng với đối tượng được đại diện bởi lớp này. Phương pháp này là tương đương với năng động của Java toán tử instanceof ngôn ngữ ... Cụ thể, nếu Class đối tượng này đại diện cho một lớp tuyên bố , phương thức này trả true nếu quy định Object đối số là một thể hiện của các lớp đại diện (hoặc của bất kỳ lớp con nào của nó); nó trả về false nếu không.

Vì cha mẹ không phải là phân lớp con, isInstance() trả về false nên cast() ném ngoại lệ. Điều này có thể vi phạm nguyên tắc của sự ngạc nhiên ít nhất nhưng nó làm việc theo cách nó được ghi lại - cast() chỉ có thể upcast, không downcast.

2

Có thể là bạn chỉ muốn sao chép/sao chép đối tượng của mình.

Trong trường hợp đó, hãy triển khai giao diện Cloneable và ghi đè lên bản sao() khi cần thiết.

public class Parent implement Cloneable { 
    public Object clone() throws CloneNotSupportedException { 
    Parent aCopy = (Parent) super.clone(); 
    ... 
    return aCopy; 
    } 
} 

public class ChildN extends Parent { 
    ... 
} 

public class Driver { 
    public static void main(String[] args) { 
     ChildN orig = new ChildN(); 
     ... 
     ChildN copy = orig.getClass().cast(orig.clone()); 
    } 
} 

Điều này thực hiện chính xác phương thức "copy()" của bạn đã cố gắng thực hiện theo cách Java.

(Có, bạn cũng có thể làm những trò chơi nội tâm lạ mắt, nhưng những phương pháp đó thất bại hoặc trở nên xấu xí ngay khi bạn không có công cụ xây dựng mặc định công khai. Clone hoạt động trong mọi trường hợp bất kể bạn là nhà thầu nào.)

+0

Cũng hoạt động! Tôi đã nghe nói rằng clone() có một danh tiếng xấu, nhưng không chắc chắn về những lý do chính xác. – user50264

+0

Đây có thể là cách "có thể" khác. Không cần phải thay đổi chữ ký phương thức (sử dụng nhân bản và trả về đối tượng) sao chép dưới dạng tên và cha mẹ vì trả về nên làm. – OscarRyz

0

Lý do công việc downcasting doesnt là bởi vì, khi bạn đưa một đối tượng cha mẹ vào một kiểu con, không có cách nào bạn có thể gọi các phương thức của kiểu con trên đối tượng cha. Nhưng nó hoạt động theo cách khác ...