2009-06-17 28 views
8

Tôi đang làm việc với một lớp C# thứ 3 có nhiều phương thức và thuộc tính tuyệt vời - nhưng khi thời gian trôi qua, tôi cần mở rộng lớp đó bằng các phương thức và thuộc tính của riêng mình. Nếu đó là mã của tôi, tôi sẽ chỉ sử dụng lớp đó làm lớp cơ sở của tôi và thêm thuộc tính và phương thức của riêng tôi lên trên - nhưng lớp này có một hàm tạo bên trong. (Theo ý kiến ​​của tôi, nó đã được sắp xếp ngắn để làm cho nhà xây dựng nội bộ ngay từ đầu - tại sao lại hạn chế khả năng phân lớp?)Có cách nào để bắt nguồn từ một lớp học với một nhà xây dựng nội bộ không?

Điều duy nhất tôi có thể nghĩ là tạo ra các phương pháp/thuộc tính của họ - nhưng đó là mẫu mã và, tốt, nó chỉ không "cảm thấy" đúng.

Có cách nào để sử dụng lớp này một lớp cơ sở không?

+1

Phần một: http://blogs.msdn.com/ericlippert/archive/2008/09/26/preventing-third-party-derivation-part-one.aspx –

+1

Phần thứ hai: http: //blogs.msdn .com/ericlippert/archive/2008/10/06/prevent-third-party-derivation-part-two.aspx –

Trả lời

0

Tôi sẽ không thảo luận xem bạn có thể xây dựng Mặt tiền của riêng bạn xung quanh lớp bên thứ ba đó hay không. Tác giả trước đó là đúng, thư viện có thể được thiết kế theo cách mà sẽ không cho phép điều này. Giả sử họ có một số lớp kết hợp có bộ đơn nên được khởi tạo theo thứ tự cụ thể hoặc như thế này - có thể có rất nhiều lỗi thiết kế (hoặc tính năng) mà nhà phát triển bên thứ 3 không bao giờ quan tâm, bởi vì họ không cho rằng bạn sẽ sử dụng thư viện của họ theo cách đó.Nhưng OK, giả sử rằng việc xây dựng một mặt tiền không phải là một nhiệm vụ không thể, và thực tế bạn chỉ có một vấn đề - có quá nhiều phương pháp bạn phải viết trình bao bọc xung quanh và không tốt để làm điều này bằng tay.

Tôi thấy 3 giải pháp để giải quyết một cách chính xác rằng vấn đề

1) Tôi giả sử rằng mới loại "năng động" của .NET 4.0 sẽ cho phép bạn để workaround vấn đề đó mà không cần phải viết "mẫu mã" Bạn nên incapsulate một thể hiện của lớp bên thứ 3 vào lớp của bạn như là một thành viên privare với từ khóa động Lớp của bạn nên được bắt nguồn từ Dynamic hoặc triển khai thực hiện giao diện IDynamicObject. Bạn sẽ phải thực hiện các chức năng/SetMember GetMember mà sẽ chuyển tiếp các cuộc gọi tới dụ đóng gói của lớp bên thứ 3

Vâng, C# 4.0 là một tương lai, Hãy xem trên các giải pháp khác:

2) Đừng viết mã theo cách thủ công nếu bạn có số lượng đáng kể các phương thức công khai (nói nhiều hơn 100). Tôi sẽ viết một ứng dụng giao diện điều khiển nhỏ sử dụng sự phản chiếu và tìm tất cả các thành viên công cộng và sau đó tự động tạo mã để gọi cá thể đóng gói. Ví dụ:

public type MethodName(params) 
{ 
    this.anInstanceOf3rdPartyClass.MethodName(params); 
} 

3) Bạn có thể làm tương tự như 2, nhưng với sự trợ giúp của các công cụ phản chiếu hiện có, ví dụ RedGate .NET Reflector. Nó sẽ giúp bạn liệt kê tất cả các lớp và phương thức chữ ký. Sau đó, dán tất cả điều này vào Word và macro VB đơn giản sẽ cho phép bạn tạo mã giống như bạn có thể làm trong 2. Lưu ý: Ngay khi bạn không sao chép mã, nhưng chỉ sao chép chữ ký phương thức, có sẵn công khai , Tôi không nghĩ rằng bạn sẽ vi phạm thỏa thuận cấp phép, nhưng dù sao cũng đáng để kiểm tra lại

2

Chỉ khi lớp học của bạn sống trong cùng một nhóm với lớp bạn muốn kế thừa. Một hàm khởi tạo bên trong giới hạn việc triển khai thực hiện cụ thể lớp trừu tượng cho assembly xác định lớp. Một lớp có chứa một hàm tạo bên trong không thể được khởi tạo bên ngoài assembly.

2

Âm thanh như một ứng dụng hoàn hảo cho phương pháp khuyến nông:

MSDN extension method docs

"phương pháp mở rộng cho phép bạn 'add' phương pháp để loại hiện có mà không cần tạo một loại có nguồn gốc mới, biên dịch lại, hoặc sửa đổi các loại gốc Các phương thức mở rộng là một kiểu phương thức tĩnh đặc biệt, nhưng chúng được gọi như thể chúng là các phương thức cá thể trên kiểu mở rộng. thực sự được định nghĩa trong một loại. "

+0

Bạn chỉ cần 'mới' nó giống như cách bạn đã làm - nó kỳ diệu có được các phương pháp mới mà bạn đã thêm vào nó. – Bruce

+0

Phương pháp mở rộng chỉ tốt ở những nơi mà phương pháp tĩnh có thể được sử dụng. Ngoài ra, không gian tên chứa lớp với các phương thức mở rộng cũng phải được bao gồm. Ví dụ: bạn không thể có thuộc tính lưu trữ trạng thái. –

+0

Đã hiểu về trạng thái - có những hạn chế. Tôi không hiểu bình luận của bạn về các phương thức tĩnh - chắc chắn, phương thức mở rộng là tĩnh, nhưng nó có quyền truy cập vào cá thể đối tượng thông qua tham số 'this'. – Bruce

2

Nếu lớp có một hàm tạo nội bộ, và không có hàm tạo công khai nào, thì điều đó cho thấy rằng các nhà thiết kế không có ý định cho nó được phân lớp. Trong trường hợp đó, bạn có thể sử dụng đóng gói, hoặc bạn có thể sử dụng các phương pháp mở rộng.

5

Bạn hỏi: "Tại sao lại hạn chế khả năng phân lớp?"

Vì thiết kế cho kế thừa là khó khăn, đặc biệt nếu bạn đang thiết kế cho các nhà phát triển khác kế thừa từ lớp học của bạn. Như Josh Bloch nói trong Java hiệu quả, bạn nên thiết kế cho kế thừa hoặc cấm nó. Theo quan điểm của tôi, trừ khi bạn có một lý do tốt để thiết kế cho thừa kế, bạn không nên làm như vậy speculatively.

Lớp học có triển khai giao diện mà bạn cũng có thể triển khai (có thể bằng cách ủy quyền hầu hết các cuộc gọi trở lại phiên bản gốc) không? Thường thì không có câu trả lời thực sự thanh lịch ở đây - và giải pháp tốt nhất sẽ phụ thuộc vào tình hình chính xác, bao gồm cả những gì bạn đang cố gắng thêm vào lớp.

Nếu bạn không thêm bất kỳ trạng thái nào nữa - chỉ là các phương pháp tiện lợi, có hiệu quả - thì các phương pháp mở rộng có thể hoạt động tốt cho bạn. Nhưng chúng không thay đổi dữ liệu mà đối tượng có khả năng lưu trữ, vì vậy nếu bạn cần thêm dữ liệu chuyên môn của riêng mình, dữ liệu đó sẽ không hoạt động.

1

Tính năng chia sẻ lại có tính năng tốt để tạo thành viên ủy quyền.

Here là ví dụ về những gì bạn có thể làm với nó. Phải mất một vài giây.

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