Tôi muốn như đánh dấu rằng setter là nội bộ trong giao diện tuy nhiên, do đó, không có cơ hội ai đó thực hiện ICustomer và ai đó bên ngoài lắp ráp sửa đổi những thuộc tính. Có cách nào tốt để làm điều này?
Không. Thành viên bất động sản là luôn là công khai, thật không may. Ngoài ra, rối tung xung quanh với mức truy cập vào các thuộc tính mà một phần của nó được chỉ định trên giao diện bị đau đớn, IIRC. Những gì bạn có thể làm là thế này:
public interface ICustomer
{
string FirstName { get; }
string SecondName { get; }
}
internal interface ICustomerWithSetMethods : ICustomer
{
void SetFirstName(string name);
void SetLastName(string name);
}
public class Customer : ICustomerWithSetMethods
Sau đó từ bên ngoài nó sẽ trông giống như Customer
chỉ thực hiện ICustomer
, nhưng từ bên mã của bạn sẽ thấy rằng nó thực hiện ICustomerWithSetMethods
.
Thật không may điều đó không chơi độc đáo nếu API của bạn cần phải khai báo bất kỳ phương pháp nào nơi bạn muốn thực sự như chỉ cần khai báo một kiểu trả về của ICustomer
, nhưng bạn sẽ thực sự biết rằng nó luôn luôn ICustomerWithSetMethods
.
Giả sử bạn vẫn muốn cho phép triển khai nhiều, bạn có thể có khả năng đi cho một lớp trừu tượng thay vì:
public abstract class CustomerBase
{
public abstract string FirstName { get; }
public abstract string LastName { get; }
internal abstract void SetFirstName(string name);
internal abstract void SetLastName(string name);
}
Bây giờ chúng ta có kỳ quặc nhẹ mà không ai bên ngoài lắp ráp có thể mở rộng CustomerBase
của bạn, bởi vì có là phương pháp trừu tượng mà họ phải ghi đè để họ thậm chí không thể xem - nhưng điều đó có nghĩa là bạn có thể sử dụng CustomerBase
ở mọi nơi trong API của mình.
Đây là phương pháp chúng tôi đã thực hiện trong Noda Time cho hệ thống lịch ở cuối - I blogged about it khi tôi lần đầu tiên đưa ra kế hoạch. Tôi nói chung là thích giao diện cho các lớp trừu tượng, nhưng lợi ích ở đây là đáng kể.
Nguồn
2012-11-28 20:59:15
Cảm ơn bạn đã hỗ trợ. Nếu tôi làm điều đó tuy nhiên, và lớp tiêu thụ sử dụng ICustomer nó không thể đến được setter. – larryq
@larryq Đó là toàn bộ vấn đề, bởi vì giao diện không cam kết với setter. Nếu bạn muốn thực hiện một giao diện nội bộ thứ hai cho biết thêm các setter bạn có thể. Tôi thường có một loạt các giao diện: đây là một ví dụ thực tế: 'IDimensionedMap' chỉ cam kết kích thước của một thực thể 2D; 'IReadMap' với các thuộc tính có thể đọc được, 'IReadMap: IDimensionedMap' cho các bản đồ chỉ đọc hoặc được tính toán, và sau đó là' IWriteMap: IReadMap'. Nhưng đây là một nhóm các lớp tiện ích mở rộng phức tạp. (Đây là hai không gian Hilbert 2d, không phải từ điển, nếu bạn tò mò.) – SAJ14SAJ
@larryq Trong khi tôi không chắc liệu bạn có cần hay không, tôi đã thêm một thực thi thay thế trong đó giao diện định nghĩa một phương thức thiết lập bên trong. – Servy