Một số người cho rằng mọi thứ có thể vượt khỏi tầm kiểm soát bằng cách sử dụng bạn bè. Tôi đồng ý, nhưng điều đó không làm giảm tính hữu dụng của nó. Tôi không chắc chắn rằng người bạn đó nhất thiết làm tổn thương mô hình OO hơn là làm cho tất cả các thành viên trong lớp của bạn công khai. Chắc chắn ngôn ngữ sẽ cho phép bạn công khai tất cả các thành viên của mình, nhưng đó là một lập trình viên có kỷ luật, tránh kiểu mẫu thiết kế đó. Tương tự như vậy, một lập trình viên có kỷ luật sẽ bảo lưu việc sử dụng bạn bè cho các trường hợp cụ thể trong trường hợp có ý nghĩa. Tôi cảm thấy nội bộ phơi bày quá nhiều trong một số trường hợp. Tại sao để lộ một lớp hoặc phương thức cho mọi thứ trong hội đồng?
Tôi có một trang ASP.NET kế thừa trang cơ sở của riêng tôi, đến lượt nó kế thừa System.Web.UI.Page. Trong trang này, tôi có một số mã xử lý báo cáo lỗi của người dùng cuối cho ứng dụng theo phương thức được bảo vệ
ReportError("Uh Oh!");
Bây giờ, tôi có một điều khiển người dùng có trong trang. Tôi muốn kiểm soát người dùng có thể gọi các phương thức báo cáo lỗi trong trang.
MyBasePage bp = Page as MyBasePage;
bp.ReportError("Uh Oh");
Nó không thể làm điều đó nếu phương thức ReportError được bảo vệ. Tôi có thể làm cho nó bên trong, nhưng nó được tiếp xúc với bất kỳ mã nào trong hội đồng. Tôi chỉ muốn nó tiếp xúc với các thành phần UI là một phần của trang hiện tại (bao gồm các điều khiển con). Cụ thể hơn, tôi muốn lớp điều khiển cơ sở của mình xác định chính xác các phương thức báo cáo lỗi và chỉ cần gọi các phương thức trong trang cơ sở.
protected void ReportError(string str) {
MyBasePage bp = Page as MyBasePage;
bp.ReportError(str);
}
Tôi tin rằng một cái gì đó như bạn bè có thể hữu ích và được triển khai bằng ngôn ngữ mà không làm cho ngôn ngữ bớt "OO" như, có thể là thuộc tính, để bạn có thể có các lớp hoặc phương thức làm bạn với các lớp hoặc phương thức cụ thể, cho phép nhà phát triển cung cấp truy cập cụ thể. Có lẽ một cái gì đó như ... (mã giả)
[Friend(B)]
class A {
AMethod() { }
[Friend(C)]
ACMethod() { }
}
class B {
BMethod() { A.AMethod() }
}
class C {
CMethod() { A.ACMethod() }
}
Trong trường hợp ví dụ trước của tôi có lẽ có một cái gì đó như sau (người ta có thể tranh luận về ngữ nghĩa, nhưng tôi chỉ đang cố gắng để có ý tưởng xuyên suốt):
class BasePage {
[Friend(BaseControl.ReportError(string)]
protected void ReportError(string str) { }
}
class BaseControl {
protected void ReportError(string str) {
MyBasePage bp = Page as MyBasePage;
bp.ReportError(str);
}
}
Như tôi thấy, khái niệm bạn bè không có rủi ro nào hơn là làm cho mọi thứ trở nên công khai, hoặc tạo các phương thức hoặc thuộc tính công khai để truy cập các thành viên. Nếu bất cứ điều gì bạn bè cho phép mức độ chi tiết khác của khả năng truy cập dữ liệu và cho phép bạn thu hẹp khả năng truy cập đó thay vì mở rộng nó với nội bộ hoặc công khai.