it-swarm-vi.com

Tại sao chúng ta cần các biến riêng tư?

Tại sao chúng ta cần các biến riêng tư trong các lớp?

Mỗi cuốn sách về lập trình tôi đã đọc đều nói đây là một biến riêng tư, đây là cách bạn định nghĩa nó nhưng dừng lại ở đó.

Từ ngữ của những lời giải thích này luôn có vẻ như tôi thực sự có một cuộc khủng hoảng niềm tin vào nghề nghiệp của chúng tôi. Những lời giải thích luôn luôn nghe như các lập trình viên khác đang làm rối tung mã của chúng tôi. Tuy nhiên, có nhiều ngôn ngữ lập trình không có biến riêng.

  1. Làm gì biến tư nhân giúp ngăn chặn?

  2. Làm thế nào để bạn quyết định nếu một tài sản cụ thể nên riêng tư hay không? Nếu theo mặc định, mọi trường NÊN ở chế độ riêng tư thì tại sao lại có các thành viên dữ liệu công khai trong một lớp?

  3. Trong trường hợp nào một biến nên được công khai?

216
mwallace

Đó không phải là vấn đề đáng tin cậy, mà là quản lý sự phức tạp.

Một thành viên công cộng có thể được truy cập từ bên ngoài lớp học, điều này cho những cân nhắc thực tế có nghĩa là "có khả năng ở bất cứ đâu". Nếu có sự cố xảy ra với một lĩnh vực công cộng, thủ phạm có thể ở bất cứ đâu, và vì vậy để theo dõi lỗi, bạn có thể phải xem xét khá nhiều mã.

Ngược lại, một thành viên riêng chỉ có thể được truy cập từ bên trong cùng một lớp, vì vậy nếu có vấn đề xảy ra với điều đó, thường chỉ có một tệp nguồn để xem xét. Nếu bạn có một triệu dòng mã trong dự án của mình, nhưng các lớp của bạn được giữ ở mức nhỏ, điều này có thể làm giảm nỗ lực theo dõi lỗi của bạn xuống 1000 lần.

Một lợi thế khác có liên quan đến khái niệm 'khớp nối'. Một thành viên công khai m của một lớp A được sử dụng bởi một lớp khác B giới thiệu một phụ thuộc: nếu bạn thay đổi m in A , bạn cũng phải kiểm tra tập quán của m in B. Tệ hơn nữa, không có gì trong lớp A cho bạn biết nơi m đang được sử dụng, vì vậy một lần nữa bạn phải tìm kiếm trong toàn bộ cơ sở mã; nếu đó là thư viện bạn đang viết, bạn thậm chí phải đảm bảo mã bên ngoài dự án của bạn không bị hỏng vì thay đổi của bạn. Trong thực tế, các thư viện có xu hướng gắn bó với chữ ký phương thức ban đầu của họ càng lâu càng tốt, bất kể đau đớn, và sau đó giới thiệu một khối các thay đổi vi phạm với một bản cập nhật phiên bản chính. Ngược lại, với các thành viên tư nhân, bạn có thể loại trừ các phụ thuộc ngay lập tức - chúng không thể được truy cập từ bên ngoài, vì vậy tất cả các phụ thuộc được chứa trong lớp.

Trong bối cảnh này, "các lập trình viên khác" bao gồm bản thân trong tương lai và quá khứ của bạn. Có thể bạn đã biết ngay bây giờ rằng bạn không nên làm điều này X với biến Y của mình, nhưng bạn chắc chắn đã quên ba tháng sau khi một khách hàng khẩn cấp cần bạn thực hiện một số tính năng, và bạn tự hỏi tại sao làm X phá vỡ Y theo những cách tối nghĩa.

Vì vậy, khi nào bạn nên đặt mọi thứ ở chế độ riêng tư: Tôi muốn nói mọi thứ ở chế độ riêng tư theo mặc định và sau đó chỉ hiển thị những phần hoàn toàn phải công khai. Bạn càng có thể làm cho riêng tư, tốt hơn.

312
tdammers

Các biến riêng giúp ngăn mọi người phụ thuộc vào một số phần nhất định trong mã của bạn. Ví dụ, giả sử bạn muốn thực hiện một số cấu trúc dữ liệu. Bạn muốn người dùng cấu trúc dữ liệu của bạn không quan tâm bạn đã triển khai nó như thế nào , mà chỉ sử dụng triển khai thông qua giao diện được xác định rõ. Lý do là nếu không có ai phụ thuộc vào việc thực hiện của bạn, bạn có thể thay đổi bất cứ khi nào bạn muốn. Ví dụ: bạn có thể thay đổi triển khai back-end để cải thiện hiệu suất. Bất kỳ nhà phát triển nào khác phụ thuộc vào việc triển khai của bạn sẽ bị hỏng, trong khi người dùng giao diện sẽ ổn. Có sự linh hoạt để thay đổi việc triển khai mà không ảnh hưởng đến người dùng lớp là một lợi ích to lớn mà việc sử dụng các biến riêng tư (và rộng hơn, đóng gói ) mang lại cho bạn.

Ngoài ra, nó không thực sự là một "cuộc khủng hoảng niềm tin". Nếu bạn đặt một phần dữ liệu công khai, bạn không thể đảm bảo rằng không có ai phụ thuộc vào dữ liệu đó. Nó thường rất thuận tiện để phụ thuộc vào một số biến cụ thể thực hiện, thay vì đi qua giao diện công cộng, đặc biệt là trong thời hạn cuối cùng. Hơn nữa, các nhà phát triển sẽ không luôn nhận ra rằng họ phụ thuộc vào thứ gì đó có thể thay đổi.

Vì vậy, loại câu trả lời câu hỏi khác của bạn, tôi hy vọng. Tất cả các chi tiết triển khai của bạn phải ở chế độ riêng tư và phần công khai phải là một giao diện nhỏ, ngắn gọn, được xác định rõ để sử dụng lớp của bạn.

111
Oleksi

Từ khóa ở đây là Encapsulation . Trong OOP bạn muốn sử dụng các biến riêng tư để thực thi đóng gói đúng đối tượng/lớp của mình.

Mặc dù các lập trình viên khác không sẵn sàng nhận bạn, họ vẫn tương tác với mã của bạn. Nếu bạn không đặt một biến riêng tư, họ cũng có thể tham chiếu nó trong mã riêng của họ mà không muốn làm hại gì cả. Tuy nhiên, nếu bạn cần quay lại lớp học và thay đổi thứ gì đó, bạn không còn biết ai sử dụng biến nào và ở đâu. Mục tiêu của đóng gói là làm cho giao diện bên ngoài của lớp rõ ràng để bạn chỉ biết các phương thức (thông thường) này có thể được sử dụng bởi những người khác.

  1. Do đó, các biến riêng đảm bảo rằng biến tương ứng chỉ còn lại trong lớp định nghĩa. Nếu bạn cần thay đổi nó, thay đổi là cục bộ của chính lớp đó.

  2. Trong các làn đường truyền thống như C++ hoặc Java, bạn thường đặt mọi thứ ở chế độ riêng tư và chỉ có thể truy cập bằng các getters và setters tương ứng. Không cần phải quyết định nhiều thực sự.

  3. Đôi khi, f.ex. trong cấu trúc C++, bạn chỉ cần một lớp như một cách để nhóm nhiều thứ lại với nhau. Ví dụ, hãy xem xét một lớp Vector có thuộc tính x và chỉ một thuộc tính y. Trong những trường hợp đó, bạn có thể cho phép truy cập trực tiếp vào các thuộc tính này bằng cách khai báo chúng công khai. Cụ thể, bạn không cần quan tâm nếu một số mã bên ngoài sửa đổi một đối tượng của lớp bằng cách viết trực tiếp các giá trị mới vào x hoặc y.

Là một điểm bổ sung, lưu ý rằng vấn đề này được coi là hơi khác nhau trong các ngôn ngữ khác. Ví dụ: các ngôn ngữ bắt nguồn mạnh mẽ trong lập trình chức năng nhấn mạnh đến tính bất biến của dữ liệu, tức là không thể thay đổi giá trị dữ liệu. Trong những trường hợp như vậy, bạn không cần phải quan tâm những gì lập trình viên khác (hay đúng hơn là mã của họ) làm gì với dữ liệu của bạn. Họ chỉ đơn giản là không thể làm bất cứ điều gì có thể ảnh hưởng đến mã của bạn, bởi vì tất cả dữ liệu là bất biến.

Do đó, trong các ngôn ngữ đó, bạn nhận được một cái gì đó gọi là nguyên tắc truy cập thống nhất , trong đó người ta cố tình không phân biệt các phương thức như getters và setters, nhưng cung cấp quyền truy cập trực tiếp vào biến/hàm. Vì vậy, bạn có thể nói rằng các khai báo riêng tư khá phổ biến hơn trong các kịch bản hướng đối tượng.

Điều này cũng cho thấy việc mở rộng kiến ​​thức của bạn để bao gồm các lĩnh vực khác khiến bạn xem các khái niệm hiện có theo một cách hoàn toàn mới.

26
Frank

Các biến riêng tư đảm bảo rằng các tham chiếu sau này nằm ngoài phạm vi của một đối tượng hoặc hàm sẽ không vô tình ảnh hưởng đến các biến khác. Đối với các dự án lập trình lớn, điều này có thể giúp tránh được rất nhiều vấn đề thú vị (thường không được trình biên dịch bắt gặp).

Ví dụ: các ngôn ngữ nguyên mẫu như Javascript có thể cho phép người dùng dán vào các biến khi họ thấy phù hợp:

function SomeObject() {
    this.a = 2; //Public (well, actually protected) variable

    this.showA = function() {
        alert(this.a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 3. Uh oh!

Nếu biến đó là riêng tư, nó sẽ không thể thay đổi từ bên ngoài:

function SomeObject() {
    var a = 2; //Private variable

    this.showA = function() {
        alert(a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 2

Điều đó nói rằng, không phải tất cả các biến cần phải riêng tư và việc sử dụng quá mức các biến riêng tư thực sự có thể làm cho mã trở nên cồng kềnh hơn. Các trường tầm thường không ảnh hưởng nghiêm trọng đến một đối tượng không cần các phương thức get()set().

Các biến riêng tư cũng giúp mở rộng mã dễ dàng hơn trong tương lai, mà không cần dựa vào tài liệu nặng như những gì nhiều biến công khai làm. Có ít mối đe dọa về việc vô tình phá vỡ chức năng nếu ít biến số có thể bị ghi đè.

Các biến công khai nên được sử dụng khi một đối tượng/hàm sẽ truy cập các đối tượng/hàm khác, vì theo quy tắc, các biến riêng không thể làm điều này. Bạn có thể có bất cứ nơi nào từ một vài đến một vài biến công khai và việc sử dụng chúng không phải là một điều xấu nếu chúng được sử dụng đúng cách.

7
Jeffrey Sweeney

Có một số câu trả lời hay trích dẫn lợi ích cho những người duy trì và người dùng trong tương lai. Tuy nhiên, cũng có những lợi ích cho thiết kế ban đầu. Nó cung cấp một điểm phân định rõ ràng giữa khi mục tiêu của bạn là làm cho mọi thứ dễ dàng hơn với chính mình và khi mục tiêu của bạn là làm cho mọi thứ dễ dàng hơn với người dùng lớp. Khi bạn chọn giữa công khai và riêng tư, nó báo hiệu cho bộ não của bạn để chuyển sang chế độ này hoặc chế độ khác và bạn kết thúc với một API tốt hơn.

Không phải ngôn ngữ mà không có sự riêng tư làm cho thiết kế như vậy là không thể, chỉ là ít có khả năng. Thay vì được nhắc viết một cái gì đó như foo.getBar(), mọi người có xu hướng nghĩ rằng một getter là không cần thiết, bởi vì nó dễ viết hơn foo.bar, nhưng sau đó quyết định đó không được xem xét lại khi bạn kết thúc với những điều quái dị dài hơn như obj.container[baz].foo.bar. Các lập trình viên chưa bao giờ làm việc trong một ngôn ngữ chặt chẽ hơn thậm chí có thể không thấy điều gì sai với điều đó.

Đó là lý do tại sao trong các ngôn ngữ không có quyền riêng tư, mọi người sẽ thường áp dụng các tiêu chuẩn đặt tên mô phỏng nó, chẳng hạn như đặt trước một dấu gạch dưới cho tất cả các thành viên "riêng tư". Đó là một tín hiệu hữu ích ngay cả khi ngôn ngữ không thi hành nó.

7
Karl Bielefeldt

Tất cả các biến phải ở chế độ riêng tư trừ khi chúng thực sự cần được công khai (điều này gần như không bao giờ, bạn nên sử dụng các thuộc tính/getters và setters).

Các biến chủ yếu cung cấp trạng thái của đối tượng và các biến riêng tư ngăn người khác đi vào và thay đổi trạng thái của đối tượng.

3
bbb

Xem bài đăng này của tôi cho một câu hỏi liên quan trên SO .

Tóm lại, đó là phạm vi biến cho phép bạn hiển thị cho người tiêu dùng mã của bạn những gì họ nên và không nên gây rối. Một biến riêng có thể chứa dữ liệu đã được "hiệu đính" bằng cách sử dụng bộ thiết lập thuộc tính hoặc phương thức xử lý để đảm bảo toàn bộ đối tượng ở trạng thái nhất quán. Thay đổi trực tiếp giá trị của biến riêng có thể khiến đối tượng trở nên không nhất quán. Bằng cách đặt nó ở chế độ riêng tư, ai đó phải làm việc rất chăm chỉ và có quyền truy cập thời gian thực sự cao, để thay đổi nó.

Do đó phạm vi thành viên thích hợp là chìa khóa trong mã tự viết tài liệu.

2
KeithS

Nó không liên quan gì đến sự tin tưởng hay sợ hãi trước các cuộc tấn công, nó chỉ liên quan đến Đóng gói - không ép buộc thông tin không cần thiết về người dùng của lớp.

Hãy xem xét các hằng số riêng - chúng không nên chứa các giá trị bí mật (chúng nên được lưu trữ ở nơi khác), chúng không thể được thay đổi, chúng không cần phải được chuyển vào lớp của bạn (nếu không chúng sẽ phải được công khai). Việc sử dụng duy nhất có thể cho chúng là các hằng số trong các lớp KHÁC. Nhưng nếu bạn làm điều đó, các lớp đó phụ thuộc vào lớp của bạn, để thực hiện công việc không liên quan đến lớp của bạn. Nếu bạn thay đổi hằng số, các lớp khác có thể bị hỏng. Điều đó thật tệ từ cả hai phía - với tư cách là nhà văn của lớp bạn, bạn muốn tự do thay đổi nhiều nhất có thể và không muốn lo lắng về những điều ngoài tầm kiểm soát của mình. Một người tiêu dùng của lớp bạn muốn có thể phụ thuộc vào các chi tiết được tiết lộ của lớp của bạn, mà không phải lo lắng về việc bạn thay đổi nó và phá vỡ mã của họ.

Một người tiêu dùng của lớp bạn muốn biết mọi thứ cần thiết để TƯƠNG TÁC với lớp của bạn và không muốn biết bất cứ điều gì về lớp của bạn mà không thay đổi cách họ làm như vậy: đó là những chuyện vặt vãnh vô ích. Nếu bạn đã sử dụng một ngôn ngữ với sự phản chiếu, bạn có thường xuyên sử dụng nó để học không phải cách một số lớp làm điều gì đó hoặc nơi nó ném một ngoại lệ bất ngờ, mà chỉ đơn giản là tên của các trường và phương thức riêng tư? Tôi đang cá cược không bao giờ. Bởi vì bạn không có sử dụng cho kiến ​​thức đó.

2
jmoreno
  • Làm gì biến tư nhân giúp ngăn chặn?

Đó là về việc làm rõ các thuộc tính và phương thức nào là giao diện và những thuộc tính nào thực sự là chức năng cốt lõi. Các phương thức/thuộc tính công khai là về mã khác thường là mã của nhà phát triển khác sử dụng các đối tượng của bạn. Tôi chưa bao giờ làm việc trên các nhóm trên 100 dự án trong cùng một dự án, nhưng theo kinh nghiệm của tôi về các nhóm 3-5 có tới 20 nhà phát triển khác sử dụng những thứ tôi đã viết, những mối quan tâm khác có vẻ ngớ ngẩn.

Lưu ý: Tôi chủ yếu là một nhà phát triển JavaScript. Tôi thường không lo lắng về việc các nhà phát triển khác xem mã của tôi và tôi hoạt động trong nhận thức đầy đủ rằng họ có thể chỉ cần xác định lại nội dung của tôi bất cứ lúc nào. Tôi cho rằng họ đủ năng lực để biết họ đang làm gì trước tiên. Nếu không, tôi không thể làm việc với một nhóm không sử dụng kiểm soát nguồn.

  • Làm thế nào để bạn quyết định nếu một tập hợp các thuộc tính cụ thể nên riêng tư hay không? Nếu theo mặc định, mọi trường NÊN ở chế độ riêng tư thì tại sao lại có các thành viên dữ liệu công khai trong một lớp?

Tôi đã từng nghĩ thật ngớ ngẩn khi đặt getters và setters vào các thuộc tính riêng tư khi bạn không thực sự thực hiện bất kỳ loại xác nhận hoặc xử lý đặc biệt nào khác của tài sản sẽ được đặt. Tôi vẫn không nghĩ rằng nó luôn luôn cần thiết, nhưng khi bạn xử lý với quy mô lớn, độ phức tạp cao, nhưng quan trọng nhất là rất nhiều nhà phát triển khác dựa vào các đối tượng của bạn hành xử một cách nhất quán, có thể hữu ích để làm mọi việc trong một cách nhất quán và thống nhất. Khi mọi người nhìn thấy các phương thức được gọi là getThatsetThat, họ biết chính xác ý định là gì và họ có thể viết các đối tượng của mình để tương tác với bạn với mong muốn họ sẽ luôn nhận được cà chua thay vì tomahtos . Nếu họ không, họ biết đối tượng của bạn đang cung cấp cho họ thứ gì đó có lẽ không nên, điều đó có nghĩa là nó cho phép một số đối tượng khác làm điều gì đó với dữ liệu đó có lẽ không nên. Bạn có thể kiểm soát điều đó khi có nhu cầu.

Ưu điểm lớn khác là dễ dàng hơn để các đối tượng của bạn xử lý hoặc giải thích các giá trị khác với getter hoặc setter dựa trên một số loại bối cảnh trạng thái khác nhau. Vì họ đang truy cập công cụ của bạn bằng một phương thức, nên việc thay đổi cách đối tượng của bạn hoạt động sau này dễ dàng hơn nhiều mà không vi phạm mã khác phụ thuộc vào phương thức đó. Nguyên tắc quan trọng là chỉ có đối tượng của bạn thực sự thay đổi dữ liệu mà bạn đã chịu trách nhiệm. Điều này đặc biệt quan trọng để giữ cho mã của bạn được ghép lỏng lẻo, đó là một chiến thắng lớn về tính di động và dễ sửa đổi.

  • Trong trường hợp nào một biến nên được công khai?

Với các hàm hạng nhất (bạn có thể truyền các hàm làm đối số), tôi không thể nghĩ ra nhiều lý do tuyệt vời khác ngoài việc không cần thiết phải làm như vậy đối với các dự án quy mô nhỏ hơn. Nếu không có nó, tôi cho rằng bạn có thể có các thành viên đang được xử lý thường xuyên và thường xuyên bởi các đối tượng khác ở mức độ có vẻ hơi khó chịu khi liên tục gọi get và đặt trên một đối tượng không thực sự chạm vào dữ liệu đó, nhưng trong đó chính nó sẽ khiến tôi tự hỏi tại sao đối tượng chịu trách nhiệm về dữ liệu đó. Nói chung, tôi có xu hướng muốn kiểm tra lại kiến ​​trúc của mình để tìm ra sai sót trước khi quyết định một thuộc tính dữ liệu công khai là cần thiết. IMO, không có gì sai với ngôn ngữ cho phép bạn làm điều gì đó thường là một ý tưởng tồi. Một số ngôn ngữ không đồng ý.

2
Erik Reppen

Tôi sẽ nói về giá trị của sự đóng gói từ một góc nhìn khác bằng một ví dụ thực tế. Cách đây khá lâu (đầu thập niên 80), một trò chơi đã được viết cho Máy tính màu Radio Shack có tên Dungeons of Daggorath. Vài năm trước, Richard Hunerlach đã chuyển nó từ một nhà lắp ráp giấy liệt kê sang C/C++ ( http://mspencer.net/daggorath/dodpcp.html ). Một thời gian sau, tôi đã nhận được mã và bắt đầu tính lại nó để đóng gói tốt hơn, ( http://dbp-consulting.com/ ware / ).

Mã đã được đưa vào các đối tượng khác nhau để xử lý lập lịch, video, đầu vào của người dùng, tạo ngục tối, quái vật, v.v. nhưng bạn chắc chắn có thể nói rằng nó được chuyển từ trình biên dịch. Nhiệm vụ lớn nhất của tôi là tăng đóng gói. Điều đó có nghĩa là tôi có được các phần khác nhau của mã để loại bỏ mũi của họ ra khỏi doanh nghiệp của nhau. Ví dụ, có nhiều nơi sẽ thay đổi các biến video trực tiếp để có hiệu quả. Một số đã làm điều đó với việc kiểm tra lỗi, một số thì không, một số đã có những ý tưởng khác biệt tinh tế về việc thay đổi điều đó có nghĩa gì. Có nhiều sự trùng lặp của mã. Thay vào đó, phần video cần có giao diện để thực hiện các tác vụ mong muốn và mã để thực hiện có thể nằm ở một nơi, một ý tưởng, một nơi để gỡ lỗi. Đó là loại điều tràn lan. Mọi đối tượng truy cập trực tiếp vào mọi đối tượng và mã khác được sao chép ở mọi nơi.

Khi mã bắt đầu bị trêu chọc, các lỗi thậm chí không được chẩn đoán đã biến mất. Mã trở nên chất lượng cao hơn. Mỗi nhiệm vụ trở thành trách nhiệm của một nơi trong mã và chỉ có một nơi duy nhất để thực hiện đúng. (Tôi vẫn tìm thấy nhiều hơn mỗi khi tôi thực hiện một lần nữa thông qua mã.)

Tất cả mọi thứ có thể nhìn thấy về mã của bạn là giao diện của bạn. Cho dù bạn có ý nghĩa hay không. Nếu bạn giới hạn khả năng hiển thị càng nhiều càng tốt thì bạn sẽ không muốn đặt mã sai vị trí sau này. Nó làm cho rõ ràng phần nào của mã chịu trách nhiệm cho dữ liệu nào. Nó làm cho thiết kế tốt hơn, sạch hơn, đơn giản hơn, thanh lịch hơn.

Nếu bạn tạo một đối tượng chịu trách nhiệm về dữ liệu của chính nó và cung cấp giao diện cho mọi người khác cần điều gì đó xảy ra, mã của bạn sẽ đơn giản hơn rất nhiều. Nó chỉ rơi ra. Bạn có những thói quen nhỏ đơn giản chỉ làm một việc. Ít phức tạp hơn == ít lỗi hơn.

2
phorgan1

Khái niệm OOP có tính kế thừa có một trong các tính năng của nó (Java hoặc C++). Vì vậy, nếu chúng ta sẽ kế thừa (có nghĩa là chúng ta sẽ truy cập vào các biến của lớp kế thừa), có khả năng ảnh hưởng đến các biến đó. Vì vậy, chúng tôi phải quyết định xem các biến có thể được thay đổi hay không.

Chỉ dành cho mục đích này, chúng tôi đang sử dụng công cụ sửa đổi truy cập trong OOP. Một trong những sửa đổi là riêng tư, có nghĩa là nó chỉ có thể được truy cập bởi lớp đó. Bất kỳ lớp nào khác không thể ảnh hưởng đến các biến đó.

Như chúng ta biết, được bảo vệ có nghĩa là nó có thể được truy cập bởi lớp sẽ kế thừa.

Tại sao có khái niệm sửa đổi trong OOP, là do những lý do này (bất kỳ lớp nào cũng có thể truy cập các biến lớp khác bằng cách sử dụng khái niệm OOP). Nếu không có khái niệm sửa đổi, điều đó có nghĩa là nó sẽ gặp khó khăn trong khi kế thừa các lớp hoặc sử dụng các khái niệm OOP khác.

1
rajNaveen

Như đã nói bởi những người khác, các biến riêng tư là tốt để tránh các lỗi sử dụng dẫn đến đối tượng rơi vào tình trạng không nhất quán và khó theo dõi các lỗi và các ngoại lệ không lường trước được.

Nhưng mặt khác, những gì hầu hết bị người khác bỏ qua là về các lĩnh vực được bảo vệ.

Một lớp con mở rộng sẽ có quyền truy cập đầy đủ vào các trường được bảo vệ, làm cho đối tượng trở nên mỏng manh như thể các trường đó là công khai, nhưng sự mong manh đó bị giới hạn ở lớp mở rộng tự nó (trừ khi nó tiếp xúc với các trường như vậy nhiều hơn).

Vì vậy, các trường công khai khó được coi là tốt và cho đến nay, lý do duy nhất để sử dụng chúng là cho các lớp được sử dụng làm tham số cấu hình (một lớp rất đơn giản với nhiều trường và không có logic, do đó lớp được truyền dưới dạng tham số một mình một số phương pháp).

Nhưng mặt khác, các trường riêng làm giảm tính linh hoạt của mã của bạn đối với người dùng khác.

Linh hoạt so với Rắc rối, ưu và nhược điểm :

Các đối tượng được khởi tạo bởi mã của bạn trong lớp Vanilla với các trường được bảo vệ là an toàn và là trách nhiệm của riêng bạn.

Mặt khác, các đối tượng mở rộng lớp của bạn với các trường được bảo vệ, được người dùng mã của bạn khởi tạo, là trách nhiệm của họ, không phải của bạn.

Vì vậy, các trường/phương thức được bảo vệ không được ghi chép tốt hoặc nếu người dùng không thực sự hiểu cách sử dụng các trường và phương thức đó, có thể gây rắc rối không cần thiết cho chính họ và cho bạn.

Mặt khác, làm cho hầu hết mọi thứ riêng tư sẽ làm giảm tính linh hoạt của người dùng và thậm chí có thể khiến họ tìm kiếm các giải pháp thay thế được duy trì, vì họ có thể không muốn tạo và duy trì một ngã ba chỉ để mọi thứ diễn ra theo cách của họ.

Vì vậy, một sự cân bằng tốt giữa riêng tư, được bảo vệ và công cộng là những gì thực sự quan trọng.

Bây giờ, để quyết định giữa riêng tư và được bảo vệ là vấn đề thực sự.

Khi nào sử dụng được bảo vệ?

Bất cứ khi nào bạn hiểu một lĩnh vực có thể rất linh hoạt, nó nên được mã hóa là được bảo vệ. Tính linh hoạt đó là: từ trở thành null (trong đó null luôn được kiểm tra và được công nhận là trạng thái hợp lệ không ném ngoại lệ), đến các ràng buộc trước khi được sử dụng bởi lớp cũ của bạn. > = 0, <100, v.v. và tự động sửa cho các giá trị vượt/chảy, ném tối đa một thông báo cảnh báo.

Vì vậy, đối với trường được bảo vệ như vậy, bạn có thể tạo một getter và chỉ sử dụng nó (thay vì sử dụng biến trường), trong khi những người dùng khác không thể sử dụng nó, trong trường hợp họ muốn linh hoạt hơn với mã cụ thể của họ, trong ví dụ của tôi có thể như : nếu họ muốn các giá trị âm hoạt động tốt ở lớp mở rộng của chúng.

1
Aquarius Power

imo @tdammers không đúng và thực sự sai lệch.

Các biến riêng tồn tại để ẩn chi tiết thực hiện. Lớp của bạn A có thể đang sử dụng array để lưu trữ điểm số. Ngày mai, bạn có thể muốn sử dụng tree hoặc priority queue. Tất cả những người dùng trong lớp của bạn cần là một cách để nhập điểm và tên addScore() và một cách để tìm ra ai là top 10 getTop(n).

Họ không cần phải truy cập cấu trúc dữ liệu cơ bản. Âm thanh tuyệt vời? Vâng, có một số hãy cẩn thận.

Dù sao thì bạn cũng không nên lưu trữ nhiều trạng thái, hầu hết là không cần thiết. Trạng thái lưu trữ sẽ làm phức tạp mã của bạn ngay cả khi nó được "tách riêng" thành một lớp cụ thể. Hãy nghĩ về nó, biến riêng đó có thể đã thay đổi bởi vì một đối tượng khác gọi là một phương thức của lớp đó. Bạn vẫn cần phải tìm ra khi nào và ở đâu phương thức đó được gọi và phương thức công khai đó có thể được gọi ở bất cứ đâu về mặt lý thuyết.

Điều tốt nhất bạn có thể làm là giới hạn số lượng trạng thái mà chương trình của bạn chứa và sử dụng các hàm thuần túy khi có thể.

0
AturSams