Trở lại những năm 2000, một đồng nghiệp của tôi nói với tôi rằng đó là một mô hình chống làm cho các phương thức công khai trở nên ảo hoặc trừu tượng.
Ví dụ, ông coi một lớp học như thế này không được thiết kế tốt:
public abstract class PublicAbstractOrVirtual
{
public abstract void Method1(string argument);
public virtual void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
// default implementation
}
}
Anh ta tuyên bố
- nhà phát triển của một lớp dẫn xuất thực hiện
Method1
và ghi đèMethod2
phải lặp lại xác thực đối số. - trong trường hợp nhà phát triển của lớp cơ sở quyết định thêm một cái gì đó xung quanh phần tùy chỉnh
Method1
hoặcMethod2
sau này, anh ta không thể làm điều đó.
Thay vào đó, đồng nghiệp của tôi đề xuất phương pháp này:
public abstract class ProtectedAbstractOrVirtual
{
public void Method1(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method1Core(argument);
}
public void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method2Core(argument);
}
protected abstract void Method1Core(string argument);
protected virtual void Method2Core(string argument)
{
// default implementation
}
}
Anh ấy nói với tôi làm cho các phương thức công khai (hoặc thuộc tính) trở nên ảo hoặc trừu tượng cũng tệ như làm cho các trường công khai. Bằng cách gói các trường vào các thuộc tính, người ta có thể chặn mọi quyền truy cập vào các trường đó sau, nếu cần. Điều tương tự cũng áp dụng cho các thành viên ảo / trừu tượng công khai: gói chúng theo cách như trong ProtectedAbstractOrVirtual
lớp cho phép nhà phát triển lớp cơ sở chặn bất kỳ cuộc gọi nào đi đến các phương thức ảo / trừu tượng.
Nhưng tôi không xem đây là một hướng dẫn thiết kế. Ngay cả Microsoft cũng không tuân theo nó: chỉ cần nhìn vào Stream
lớp để xác minh điều này.
Bạn nghĩ gì về hướng dẫn đó? Nó có ý nghĩa gì không, hay bạn nghĩ nó quá phức tạp với API?
protected
hữu ích nhất khi bạn muốn đưa các thành viên riêng của lớp trừu tượng đến các lớp dẫn xuất. Trong mọi trường hợp, tôi không đặc biệt quan tâm đến ý kiến của bạn bè bạn; chọn công cụ sửa đổi truy cập có ý nghĩa nhất cho tình huống cụ thể của bạn.
virtual
cho phép ghi đè tùy chọn. Phương pháp của bạn có lẽ nên được công khai, bởi vì nó có thể không bị ghi đè. Làm phương thứcabstract
buộc bạn phải ghi đè chúng; có lẽ chúng nênprotected
, bởi vì chúng không đặc biệt hữu ích trongpublic
ngữ cảnh.