2011-01-10 16 views
16

Tôi đã tự hỏi tại sao Java được thiết kế mà không có chỉ thị friend có sẵn trong C++ để cho phép kiểm soát tốt hơn các phương thức và biến mẫu nào có sẵn từ bên ngoài gói trong đó một lớp đã được định nghĩa.Tại sao chỉ thị bạn bè bị thiếu trong Java?

Tôi không thấy bất kỳ lý do thiết thực nào cũng như bất kỳ hạn chế cụ thể nào, có vẻ như đó chỉ là vấn đề thiết kế nhưng sẽ không tạo ra bất kỳ sự cố nào nếu được thêm vào ngôn ngữ.

Trả lời

9

Dưới đây là một vài lý do ra khỏi đỉnh đầu của tôi:

  • bạn là không cần thiết. Rất thuận tiện, nhưng không bắt buộc phải có
  • người bạn hỗ trợ thiết kế kém. Nếu một lớp yêu cầu bạn bè truy cập vào một lớp khác, bạn đang làm sai. (xem ở trên, thuận tiện, không bắt buộc).
  • ngắt kết nối bạn bè. Về cơ bản, tất cả các cá nhân của tôi đều thuộc về tôi, và anh chàng kia ở đó (bạn của tôi).
+3

+1 cho đóng gói :) – fresskoma

+20

–1 để đóng gói. Đây là một sự hiểu lầm phổ biến. Nó chỉ đơn giản là sai. Mặc dù đúng là 'bạn' * có thể * được sử dụng để phá vỡ đóng gói, vì vậy các tính năng khác có thể bị lạm dụng. Được sử dụng đúng cách, 'friend' * tăng cường * đóng gói bởi vì nó cho phép kiểm soát truy cập chi tiết hơn:' friend' thay thế sử dụng 'public', không sử dụng' private'. [Giải thích kỹ thuật tại C++ FAQ] (http://www.parashift.com/c++-faq-lite/friends.html#faq-14.2) (Điều đó nói rằng, tôi hoàn toàn hài lòng với khả năng hiển thị gói, nhưng tuyên bố rằng 'người bạn 'phá vỡ đóng gói vẫn còn sai.) –

+1

@KonradRudolph Hoàn toàn đồng ý. Các lớp bạn bè là điều cần thiết để tách các mối quan tâm. Ví dụ, tôi có một lớp 'Serializer' nên được phép ghi vào các trường của một cá thể, vì vậy tôi cho phép bạn truy cập. Các lớp khác, không thể ghi cụ thể vào các trường và phải đi qua giao diện mà tôi cung cấp. Cách duy nhất bạn có thể làm điều này trong Java là đưa mọi thứ vào cùng một gói. – crush

10

Nói chung tôi nghĩ đó là vì sự phức tạp về nhận thức được thêm vào và số lượng trường hợp thấp trong đó nó tạo ra sự cải thiện.

Tôi sẽ nói rằng số lượng cực lớn các dòng java trong sản xuất tại thời điểm này có thể chứng thực rằng từ khóa friend không thực sự là một mất mát lớn :).

Vui lòng xem câu trả lời của @ dwb để biết một số lý do cụ thể hơn.

+3

số lượng cực lớn các dòng java trong sản xuất tại thời điểm này có thể chứng thực rằng bất kỳ lựa chọn thiết kế ngẫu nhiên nào trong java đều được devine. – irreputable

+0

@irreputable Nice comeback. Tuy nhiên tôi đã nói đùa một nửa :) –

+0

'người bạn' tồn tại ở dạng hiển thị gói. Nó không linh hoạt trong Java. – crush

2

Tại sao không đơn giản nghĩ rằng Java yêu cầu các lớp bạn bè phải được đặt cùng? Chế độ hiển thị gói riêng tư cho phép mọi người từ cùng một gói truy cập các thành viên đó. Vì vậy, bạn không chỉ giới hạn những người bạn đã khai báo rõ ràng, mà còn cho phép bất kỳ người bạn (hiện tại hoặc tương lai) thay đổi một số thành viên được thiết kế đặc biệt cho mục đích này (nhưng không phải là công cụ riêng tư của bạn). Bạn vẫn có thể hoàn toàn dựa vào đóng gói.

+2

Vấn đề ở đây là bất kỳ lớp nào có thể yêu cầu là thành viên của bất kỳ gói nào. Điều này sẽ là tương đương với tôi nói với một nhân viên bảo vệ rằng tôi là bạn của bạn và nhân viên bảo vệ cho phép tôi tìm kiếm phòng của bạn. – Powerlord

+0

Điều đó không hoàn toàn đúng (bạn không thể khai báo một lớp học thuộc về gói java. *), Và bên cạnh đó, nếu ai đó thực sự cần loại hack này (đặt một lớp vào org.apache.commons.logging chỉ để xem thành viên gói riêng), họ có thể sử dụng rất tốt sự phản chiếu và setVisible (true). Nhưng tôi không nói về hack. API tiêu chuẩn Java sử dụng chuyên sâu các thành viên riêng tư của gói. –

+2

@R. Bemrose: Cơ chế hiển thị riêng tư/được bảo vệ/công khai/gói không phải là tính năng bảo mật. Đó là một tính năng lập trình được thiết kế để hỗ trợ đóng gói. – JeremyP

2

Chỉ cần để thêm vào câu trả lời khác:

Có là mặc định gói tầm nhìn trong Java. Vì vậy, bạn có thể gọi tất cả các lớp trong cùng một gói hàng xóm. Trong trường hợp đó, bạn có quyền kiểm soát rõ ràng những gì bạn hiển thị cho những người hàng xóm - chỉ các thành viên có khả năng hiển thị gói.

Vì vậy, nó không thực sự là một người bạn nhưng có thể tương tự. Và có, điều này cũng dẫn đến thiết kế xấu ...

4

Ngoài khả năng hiển thị gói nói trên, Java cũng cung cấp các lớp bên trong và ẩn danh không chỉ là bạn bè theo mặc định, mà còn tự động tham chiếu đến lớp chứa. Vì việc tạo các lớp trợ giúp như vậy có lẽ là cách hợp lý duy nhất để sử dụng friend trong C++, Java không cần nó vì nó có một cơ chế khác cho điều đó. Iterator là một ví dụ rất tốt về điều này.

+0

Bên trong nhưng không có một phần. – Vozzie

+0

@Vozzie, đúng, nhưng điều này có liên quan gì đến 'bạn bè'? –

2

Theo tôi, một số tính năng bạn bè (không nhất thiết phải rất giống với C++) sẽ rất hữu ích trong một số tình huống trong Java. Hiện tại chúng tôi có gói truy cập riêng tư/truy cập mặc định để cho phép cộng tác giữa các lớp được ghép chặt chẽ trong cùng một gói (ví dụ: StringStringBuffer), nhưng điều này sẽ mở giao diện triển khai riêng tư lên toàn bộ gói. Giữa các gói, chúng tôi có các hacks phản chiếu ác gây ra một loạt các vấn đề.

Có một chút biến chứng khác khi thực hiện điều này trong Java.C++ bỏ qua các hạn chế truy cập trong khi giải quyết quá tải chức năng (và tương tự) - nếu một chương trình biên dịch #define private public không nên làm bất cứ điều gì. Java (chủ yếu) loại bỏ các thành viên không thể truy cập. Nếu tình bạn cần phải được đưa vào tài khoản thì độ phân giải phức tạp hơn và ít rõ ràng hơn.

6

Chỉ một lập trình viên rất ngây thơ và thiếu kinh nghiệm sẽ chủ trương chống lại bạn bè. Tất nhiên nó có thể bị lạm dụng, nhưng vì vậy có thể dữ liệu công khai, nhưng khả năng đó được cung cấp.

Trái với ý kiến ​​phổ biến, dưới đây là nhiều trường hợp, đặc biệt đối với khả năng cơ sở hạ tầng, nơi bạn bè truy cập dẫn đến thiết kế BETTER hơn, không kém thiết kế. Sự đóng gói thường bị vi phạm khi một phương thức được FORCED được công bố khi nó thực sự không nên, nhưng chúng ta không còn lựa chọn nào vì Java không hỗ trợ bạn bè.

+1

Tôi ước tôi có thể upvote câu trả lời này 100x. Tư tưởng "người bạn xấu" này là một ý tưởng nguy hiểm. – crush

+0

Tôi sẽ đề nghị rằng chỉ một lập trình ngây thơ và thiếu kinh nghiệm nghĩ rằng họ cần để cho bạn bè của họ chơi với tất cả các cá nhân của họ. Nó phá vỡ đóng gói và gây ra không có kết thúc tàn phá, khi khác, phương pháp tiếp cận đơn giản hơn có sẵn. –

2

Hoàn toàn đồng ý với tuyên bố spaceghost trong his answer

Trái ngược với quan điểm phổ biến, đây là nhiều trường hợp, đặc biệt đối với khả năng cơ sở hạ tầng, nơi truy cập người bạn dẫn đến thiết kế tốt hơn, thiết kế không thua kém.

Ví dụ của tôi rất đơn giản - nếu lớp A phải cung cấp giao diện "người bạn" đặc biệt cho lớp B bằng java, chúng tôi phải đặt chúng vào cùng một gói. Không có ngoại lệ. Trong trường hợp đó nếu A là bạn của B và B là bạn của C, A phải là bạn của C không phải lúc nào cũng đúng. Điều này "tình bạn transitivity" phá vỡ đóng gói nhiều hơn thì bất kỳ vấn đề mà C + + tình bạn có thể dẫn đến.