2010-01-15 41 views
7

Tôi cần tạo một lớp với chính xác các phương thức giống như java.lang.String.Làm thế nào để tạo một bản sao lớp String?

Cách tốt nhất để làm điều này trong Java là gì?

Tôi biết rằng tôi không thể mở rộng lớp Chuỗi vì nó là final. Tôi không xem xét các giải pháp mà tôi cần sao chép mã nguồn của java.lang.String. Ví dụ, giả sử rằng tôi cần chức năng length() trong lớp tùy chỉnh của tôi có tên là MyString, có phương thức 'myLength() `tương ứng.

Cách tốt nhất để triển khai myLength() là gì?

Tôi không xem xét các thuật toán khác nhau để tìm hiểu độ dài của một chuỗi nhưng để sử dụng lại phương pháp length() của String. Bây giờ khi tôi đã có sẵn MyString lớp học, tôi có thể sử dụng nó ở bất cứ đâu để thao tác tùy chỉnh của mình.

+7

Vấn đề thực tế bạn đang cố giải quyết là gì? – ZoFreX

+0

Tôi đang cố gắng tìm ra mẫu thiết kế nào phù hợp nhất cho loại vấn đề này. – Thunderhashy

+1

Tôi luôn tự hỏi, tại sao String là cuối cùng trong Java? Chắc chắn, nó cung cấp tất cả các chức năng tôi từng cần, và không bao giờ nghĩ đến một hoạt động đòi hỏi một phần mở rộng của chuỗi lớp, nhưng bạn vẫn sẽ không bao giờ biết những gì ai đó có thể cần! – Alex

Trả lời

5

Từ câu hỏi của bạn có vẻ như điều bạn đang tìm kiếm rất đơn giản delegation:

class MyString { 

    String delegate; // The actual string you delegate to from your class 

    public MyString(String delegate) { 
    this.delegate = delegate; // Assign the string that backs your class 
    } 

    int length() { 
    return delegate.length(); // Delegate the method call to the string 
    } 

    // other methods that delegate to the string field 
} 
+0

Điều này có vẻ tốt. Nhưng tôi có thể làm MyString strAbc = "Đây là chuỗi của tôi" không? Tôi đang tìm một bản sao chính xác của Chuỗi. Trong giải pháp của bạn, tôi sẽ cần phải vượt qua String trong constructor. – Thunderhashy

+0

@ Harsha, những gì bạn muốn chỉ đơn giản là không thể. –

+0

@Paul Bạn có thể giải thích? – Thunderhashy

2

Tạo một lớp mới (nó sẽ cần một gói phần mềm khác nhau, tất nhiên, thực hiện cùng một giao diện và thêm tất cả các phương thức public từ lớp String (đọc javadoc để chắc chắn rằng bạn có tất cả mọi thứ).

tôi phải thừa nhận đây là bài tập về nhà.

8

Kể từ final lớp không thể được subclassed, tạo ra một lớp mới mà có một trường hợpString bên trong và hoạt động trên đối tượng này.

public class MyString { 
    private String s; 

    public MyString(String s) { 
    setInternalString(s); 
    } 

    public int myLength() { 
    return getInternalString().length(); 
    } 

    private void setInternalString(String s) { 
    this.s = s; 
    } 

    private String getInternalString() { 
    return this.s == null ? "" : this.s; 
    } 
} 
+2

Ủy quyền được gọi. –

3

Tôi giả sử bạn có nghĩa là java.lang.String. Tuy nhiên, bạn không thể thay thế String bằng lớp học của riêng bạn. Bạn có thể tạo một lớp khác với cùng phương thức (bằng cách sao chép mã nguồn và thay đổi khai báo gói), nhưng bạn sẽ không thể chuyển các cá thể của lớp đó sang các phương thức yêu cầu String.

Điều này sẽ trả lời một câu hỏi quan trọng: tại sao bạn nghĩ bạn muốn làm điều này?

+0

Tôi không muốn tạo một lớp chỉ bằng cách sao chép tất cả các phương thức từ lớp String. Câu hỏi này được hỏi với tôi trong một cuộc phỏng vấn. – Thunderhashy

+3

Có thể đó là một câu hỏi mẹo và bạn phải giải thích cho họ lý do tại sao thực hiện điều này sẽ ngăn cản bạn liên kết với Java API gần như hiện tại. – erickson

+1

Một câu trả lời khác cho cuộc phỏng vấn sẽ chỉ ra rằng String thực hiện CharSequence và bạn có thể tạo các triển khai khác. Tất nhiên, điều đó không giúp ích nếu các API sử dụng chuỗi ersatz yêu cầu một String thay vì một CharSequence. –

0

Nếu bạn chỉ muốn ghi đè một phần của hành vi Chuỗi bạn có thể thử sử dụng proxy động. Tra cứu java.lang.reflect.Proxy trong API.

+0

Hỗ trợ proxy động tích hợp chỉ hoạt động với giao diện. ASM và các thư viện bytecode khác có thể làm việc với các lớp, nhưng tôi không chắc chắn về các lớp cuối cùng. – erickson

3

Proxy mẫu thiết kế, tôi đoán vậy. Đó là một câu hỏi ngu ngốc, mặc dù (không phải là một sự phản ánh trên người hỏi, nhưng trên người hỏi anh ta nó trong một cuộc phỏng vấn việc làm). Có thể người hỏi bạn đã không nhận ra rằng String là cuối cùng? Nếu không thì tôi không thể nghĩ tại sao họ lại hỏi.

+1

Tôi nghĩ thử thách thực sự nằm trong thực tế là Chuỗi là cuối cùng. Nếu không câu trả lời là khá đơn giản isnt nó? Chỉ cần mở rộng chuỗi và bạn đang thực hiện với. – Thunderhashy

1

Bạn có thể sử dụng refactoring: Replace inheritance with delegation, đó là cơ bản (như trong câu trả lời trước) để tạo ra một instance variable của loại mong muốn và thực hiện tất cả các phương thức của nó trong lớp mới và truyền thông điệp cho chúng.

Tạo trường cho lớp cha, điều chỉnh các phương thức để ủy quyền cho lớp cha và xóa lớp con.

https://www.refactoring.com/catalog/repInherWithDel.gif

Bạn sẽ nhận thấy điều này là rất nhiều đánh máy, đó là khi một IDE tốt đi kèm tiện dụng.

Video sau đây cho biết cách IntelliJ IDEA 9 thực hiện.

http://img43.imageshack.us/img43/5647/capturadepantalla201001k.png

8

Đi qua những câu trả lời khác nhau ở đây, và bị tắc nghẽn thông tin cập nhật và làm rõ, dường như những gì mà hỏi muốn là một lớp trông, mùi và âm thanh như một String, nhưng không phải vậy.

Đó là họ muốn để có thể làm:

MyString string = "String!!"; 

này không thể làm việc, kể từ java.lang.String là một lớp học cuối cùng, và như vậy mỗi "String" rằng trình biên dịch tạo ra sẽ là một đối tượng java.lang.String, vì đây là không phải là đối tượng MyString mà chúng không thể được gán cho nhau.

Trong ngôn ngữ được gõ yếu, bạn có thể tạo một lớp như vậy, vì nếu lớp trông, có mùi và âm thanh như duck, sau đó đến tất cả ý định và mục đích, đó là vịt. Java, tuy nhiên, là một ngôn ngữ gõ mạnh mẽ, và một con vịt chỉ là một con vịt nếu nó xảy ra từ Anatidae family of birds.

+0

+1 điều đó đúng. SO người dùng đã yêu cầu một bản sao String và không phải là một đại biểu, nơi một đại biểu vẫn sẽ tạo ra một đối tượng String. –

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