Câu hỏi Tại sao sử dụng getters và setters / accessors? [đã đóng]


Lợi thế của việc sử dụng getters và setters là gì - chỉ nhận và đặt - thay vì chỉ sử dụng các trường công khai cho các biến đó?

Nếu getters và setters đã từng làm nhiều hơn là chỉ đơn giản get / set, tôi có thể tìm ra cái này một cách nhanh chóng, nhưng tôi không rõ 100% như thế nào:

public String foo;

là bất kỳ tồi tệ hơn:

private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }

Trong khi đó, trước đây phải mất rất ít mã soạn sẵn.


1305
2017-10-14 18:20


gốc


@Dean J: Sao chép với nhiều câu hỏi khác: stackoverflow.com/search?q=getters+setters - Asaph
Tất nhiên, cả hai đều đều xấu khi đối tượng không cần một tài sản được thay đổi. Tôi muốn làm mọi thứ riêng tư, và sau đó thêm getters nếu hữu ích, và setters nếu cần thiết. - Tordek
Google "người truy cập là ác" - OMG Ponies
"Người truy cập là ác" nếu bạn tình cờ viết mã chức năng hoặc các đối tượng bất biến. Nếu bạn tình cờ viết các đối tượng có thể thay đổi trạng thái, thì chúng rất cần thiết. - Christian Hayter
Nói, đừng hỏi. pragprog.com/articles/tell-dont-ask - Dave Jarvis


Các câu trả lời:


Có thực sự nhiều lý do chính đáng xem xét sử dụng accessors thay vì trực tiếp phơi bày các trường của một lớp - ngoài chỉ là đối số của việc đóng gói và làm cho các thay đổi trong tương lai dễ dàng hơn.

Dưới đây là một số lý do tôi biết:

  • Đóng gói hành vi liên quan đến việc nhận hoặc thiết lập thuộc tính - điều này cho phép các chức năng bổ sung (như xác thực) được thêm dễ dàng hơn sau này.
  • Ẩn biểu diễn bên trong của thuộc tính trong khi phơi bày thuộc tính bằng cách sử dụng biểu diễn thay thế.
  • Cách ly giao diện công khai của bạn khỏi thay đổi - cho phép giao diện công khai duy trì liên tục trong khi thay đổi triển khai mà không ảnh hưởng đến người tiêu dùng hiện tại.
  • Kiểm soát tuổi thọ và quản lý bộ nhớ (xử lý) ngữ nghĩa của tài sản - đặc biệt quan trọng trong môi trường bộ nhớ không được quản lý (như C ++ hoặc Objective-C).
  • Cung cấp điểm chặn gỡ lỗi khi một thuộc tính thay đổi khi chạy - gỡ lỗi khi nào và ở đâu một thuộc tính được thay đổi thành một giá trị cụ thể có thể khá khó nếu không có điều này bằng một số ngôn ngữ.
  • Cải thiện khả năng tương tác với các thư viện được thiết kế để hoạt động chống lại getter / setters thuộc tính - Mocking, Serialization và WPF đến với tâm trí.
  • Cho phép người thừa kế thay đổi ngữ nghĩa về cách hoạt động của thuộc tính và được hiển thị bằng cách ghi đè các phương thức getter / setter.
  • Cho phép getter / setter được truyền xung quanh dưới dạng các biểu thức lambda chứ không phải là các giá trị.
  • Getters và setters có thể cho phép các cấp độ truy cập khác nhau - ví dụ việc nhận được có thể là công khai, nhưng tập hợp có thể được bảo vệ.

794
2017-10-14 18:47



+1. Chỉ cần thêm: Cho phép tải chậm. Cho phép sao chép khi ghi. - NewbiZ
@bjarkef: Tôi tin public phương thức truy cập gây trùng lặp mã và hiển thị thông tin. Người truy cập công cộng không cần thiết cho việc sắp xếp (serialization). Trong một số ngôn ngữ (Java), public nhận được accessors không thể có kiểu trả về thay đổi mà không phá vỡ các lớp phụ thuộc. Hơn nữa, tôi tin rằng họ chạy ngược với các nguyên tắc OO. Xem thêm: stackoverflow.com/a/1462424/59087 - Dave Jarvis
@sbi: Một thứ được mua bằng cách sử dụng một setter thuộc tính, ngay cả trong một framework được thiết kế tốt, là khả năng có một đối tượng thông báo cho một đối tượng khác khi một thuộc tính thay đổi. - supercat
@supercat: Tuy nhiên, tôi không, nói chung, quảng bá dữ liệu công khai. Thông báo về các đối tượng khác cũng có thể được thực hiện từ các phương thức thực cung cấp một sự trừu tượng đáng kể trên một vùng chứa dữ liệu đơn thuần với (nhiều hay ít) trường dữ liệu công khai. Thay vì plane.turnTo(dir); plane.setSpeed(spd); plane.setTargetAltitude(alt); plane.getBreaks().release(); tôi muốn nói rằng plane.takeOff(alt). Những trường dữ liệu bên trong nào cần được thay đổi để đưa máy bay vào takingOff chế độ không phải là mối quan tâm của tôi. Và những thứ khác (breaks) phương thức thông báo tôi cũng không muốn biết. - sbi
@ BenLee: Tôi thực sự không biết làm thế nào để nói nó. "Người truy cập" chỉ là một từ đồng nghĩa cho "getters / setters", và trong hai ý kiến ​​đầu tiên của tôi, tôi đã giải thích lý do tại sao những người đó là lạm dụng thuật ngữ "OOP". Nếu bạn cần tiếp cận nó và điều khiển trực tiếp trạng thái, nó không phải là một đối tượng trong ý nghĩa OOP của thuật ngữ đó. - sbi


Bởi vì 2 tuần (tháng, năm) kể từ bây giờ khi bạn nhận ra rằng setter của bạn cần phải làm hơn hơn là chỉ đặt giá trị, bạn cũng sẽ nhận ra rằng thuộc tính đã được sử dụng trực tiếp trong 238 lớp khác :-)


389
2017-10-14 18:23



Tôi đang ngồi và nhìn chằm chằm vào một ứng dụng dòng 500k, nơi nó không bao giờ cần thiết. Điều đó nói rằng, nếu nó cần thiết một lần, nó sẽ bắt đầu gây ra một cơn ác mộng bảo trì. Đủ tốt cho một dấu kiểm cho tôi. - Dean J
Tôi chỉ có thể ghen tị với bạn và ứng dụng của bạn :-) Điều đó nói rằng, nó thực sự phụ thuộc vào ngăn xếp phần mềm của bạn. Delphi, ví dụ (và C # - tôi nghĩ?) Cho phép bạn định nghĩa các thuộc tính là công dân lớp 1, nơi họ có thể đọc / ghi một trường trực tiếp ban đầu nhưng - bạn cần nó - làm như vậy thông qua các phương thức getter / setter. Mucho thuận tiện. Java, than ôi, không - chưa kể đến tiêu chuẩn javabeans mà buộc bạn phải sử dụng getters / setters. - ChssPly76
Trong khi điều này thực sự là một lý do tốt để sử dụng accessors, nhiều môi trường lập trình và biên tập viên bây giờ cung cấp hỗ trợ cho refactoring (hoặc trong IDE hoặc như miễn phí add-in) mà phần nào làm giảm tác động của vấn đề. - LBushkin
có vẻ như tối ưu hóa trước khi trưởng thành - cmcginty
Câu hỏi bạn cần hỏi khi bạn tự hỏi có nên thực hiện getters và setters là: Tại sao người dùng của một lớp học cần truy cập vào nội bộ của lớp học? Nó không thực sự quan trọng cho dù họ làm điều đó trực tiếp hoặc được che chắn bởi một lớp giả mỏng - nếu người dùng cần truy cập vào các chi tiết thực hiện, thì đó là một dấu hiệu cho thấy lớp không cung cấp đủ sự trừu tượng. Xem thêm nhận xét này. - sbi


Một lĩnh vực công cộng không phải là tồi tệ hơn một cặp getter / setter mà không có gì ngoại trừ việc trả lại trường và gán cho nó. Đầu tiên, rõ ràng là (trong hầu hết các ngôn ngữ) không có sự khác biệt về chức năng. Bất kỳ sự khác biệt nào cũng phải nằm trong các yếu tố khác, như khả năng bảo trì hoặc khả năng đọc.

Một lợi thế được đề cập đến của các cặp getter / setter, không phải. Có tuyên bố rằng bạn có thể thay đổi việc triển khai và khách hàng của bạn không phải được biên dịch lại. Giả sử, setters cho phép bạn thêm chức năng như xác nhận sau này và khách hàng của bạn thậm chí không cần phải biết về nó. Tuy nhiên, việc thêm xác thực vào một setter là một sự thay đổi cho các điều kiện tiên quyết của nó, vi phạm hợp đồng trước, đó là, khá đơn giản, "bạn có thể đặt bất cứ điều gì ở đây, và bạn có thể nhận được điều tương tự sau đó từ getter".

Vì vậy, bây giờ bạn đã phá vỡ hợp đồng, thay đổi mọi tập tin trong codebase là một cái gì đó bạn nên làm, không tránh. Nếu bạn tránh nó, bạn đang giả định rằng tất cả các mã giả định hợp đồng cho các phương thức đó là khác nhau.

Nếu đó không phải là hợp đồng, thì giao diện cho phép khách hàng đặt đối tượng vào trạng thái không hợp lệ. Điều đó hoàn toàn ngược lại với việc đóng gói Nếu trường đó có thể không thực sự được thiết lập để bất cứ điều gì từ đầu, tại sao không phải là xác nhận có từ đầu?

Lập luận tương tự này áp dụng cho các lợi thế khác được cho là của các cặp getter / setter pass-through này: nếu sau này bạn quyết định thay đổi giá trị đang được thiết lập, bạn đang phá vỡ hợp đồng. Nếu bạn ghi đè lên chức năng mặc định trong một lớp dẫn xuất, theo cách vượt ra ngoài một vài sửa đổi vô hại (như đăng nhập hoặc hành vi không quan sát khác), bạn đang phá vỡ hợp đồng của lớp cơ sở. Đó là sự vi phạm Nguyên tắc thay thế Liskov, được coi là một trong các nguyên lý của OO.

Nếu một lớp có những getters câm và setters cho mọi lĩnh vực, sau đó nó là một lớp học mà không có bất biến nào, không hợp đồng. Đó có thực sự là thiết kế hướng đối tượng không? Nếu tất cả các lớp có những getters và setters, nó chỉ là một người giữ dữ liệu câm, và người giữ dữ liệu câm nên trông giống như người giữ dữ liệu câm:

class Foo {
public:
    int DaysLeft;
    int ContestantNumber;
};

Việc thêm các cặp getter / setter pass-through vào một lớp như vậy sẽ không thêm giá trị nào. Các lớp khác nên cung cấp các hoạt động có ý nghĩa, không chỉ các hoạt động mà các trường đã cung cấp. Đó là cách bạn có thể xác định và duy trì các bất biến hữu ích.

Khách hàng: "Tôi có thể làm gì với đối tượng của lớp học này?"
Nhà thiết kế: "Bạn có thể đọc và viết một số biến."
Khách hàng: "Ồ ... tuyệt, tôi đoán vậy?"

Có những lý do để sử dụng getters và setters, nhưng nếu những lý do đó không tồn tại, làm cho các cặp getter / setter trong tên của các vị thần đóng gói sai không phải là một điều tốt. Các lý do hợp lệ để tạo ra những người theo dõi hoặc định cư bao gồm những điều thường được đề cập đến như những thay đổi tiềm năng mà bạn có thể thực hiện sau này, như xác thực hoặc các biểu diễn nội bộ khác nhau. Hoặc có thể giá trị sẽ được đọc bởi khách hàng nhưng không thể ghi (ví dụ, đọc kích thước của từ điển), do đó, một getter đơn giản là một lựa chọn tốt đẹp. Nhưng những lý do đó nên ở đó khi bạn lựa chọn, và không chỉ là một điều tiềm năng mà bạn có thể muốn sau này. Đây là một ví dụ của YAGNI (Bạn không cần nó).


307
2017-08-24 10:55



Câu trả lời hay (+1). Chỉ trích duy nhất của tôi là nó đã cho tôi một vài lần đọc để tìm ra cách "xác nhận" trong đoạn cuối cùng khác với "xác nhận" trong số đầu tiên (mà bạn đã ném ra trong trường hợp thứ hai nhưng được quảng bá ở trước); điều chỉnh từ ngữ có thể giúp ích trong vấn đề đó. - Lightness Races in Orbit
Đây là một câu trả lời tuyệt vời nhưng thời đại hiện tại đã quên mất những gì "ẩn thông tin" là gì hoặc nó là gì. Họ không bao giờ đọc về bất biến và trong nhiệm vụ của họ cho hầu hết nhanh nhẹn, không bao giờ vẽ biểu đồ chuyển đổi trạng thái đó đã xác định những gì các trạng thái pháp lý của một đối tượng và do đó những gì không. - Darrell Teague
Một quan sát quan trọng là getters là hữu ích hơn nhiều so với setters. Một getter có thể trả về một giá trị tính toán, hoặc một giá trị được tính toán được lưu trữ. Tất cả một setter có thể làm là một số xác nhận và hơn thay đổi private cánh đồng. Nếu một lớp không có người định cư thì thật dễ dàng để làm cho nó không thay đổi được. - Raedwald
Er, tôi đoán bạn không biết những gì một bất biến lớp là. Nếu nó là một cấu trúc không tầm thường, nó khá nhiều có nghĩa là nó có bất biến để duy trì và một đơn giản là không thể thiết kế nó mà không có những người trong tâm trí. "Đã xảy ra lỗi, một thành viên đã được cập nhật sai." cũng khá nhiều lần đọc như "Cập nhật thành viên vi phạm các bất biến lớp". Một lớp được thiết kế tốt không cho phép mã máy khách vi phạm các bất biến của nó. - R. Martinho Fernandes
1 cho 'chủ sở hữu dữ liệu câm nên trông giống như người giữ dữ liệu câm' Thật không may, tất cả mọi người dường như thiết kế tất cả mọi thứ xung quanh chủ sở hữu dữ liệu câm những ngày này, và rất nhiều khuôn khổ thậm chí yêu cầu nó ... - Joeri Hendrickx


Rất nhiều người nói về những lợi thế của getters và setters nhưng tôi muốn chơi ủng hộ của ma quỷ. Ngay bây giờ tôi đang gỡ lỗi một chương trình rất lớn, nơi các lập trình viên quyết định làm cho mọi thứ getters và setters. Điều đó có vẻ tốt đẹp, nhưng đó là một cơn ác mộng kỹ thuật ngược lại.

Giả sử bạn đang xem qua hàng trăm dòng mã và bạn gặp phải điều này:

person.name = "Joe";

Đó là một đoạn mã đơn giản đẹp cho đến khi bạn nhận ra một setter của nó. Bây giờ, bạn làm theo setter đó và thấy rằng nó cũng đặt person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName và gọi person.update (), sẽ gửi một truy vấn tới cơ sở dữ liệu, vâng, đó là nơi rò rỉ bộ nhớ của bạn đã xảy ra.

Hiểu được một đoạn mã cục bộ ngay từ cái nhìn đầu tiên là một thuộc tính quan trọng của khả năng đọc tốt mà getters và setters có xu hướng phá vỡ. Đó là lý do tại sao tôi cố gắng tránh chúng khi tôi có thể, và giảm thiểu những gì họ làm khi tôi sử dụng chúng.


75
2017-10-14 21:00



Vâng. Hiện đang tái cấu trúc một codebase lớn, và đây là một cơn ác mộng. Các getters và setters làm theo cách quá nhiều, bao gồm gọi getters khác rất bận rộn và setters mà kết thúc làm giảm khả năng đọc không có gì. Xác nhận là một lý do tuyệt vời để sử dụng các trình truy cập, nhưng việc sử dụng chúng để làm nhiều hơn thế có vẻ như loại bỏ bất kỳ lợi ích tiềm năng nào. - Fadecomic
Đây là lập luận chống lại cú pháp đường, không chống lại người định cư nói chung. - Phil
Đúng và đúng nhưng hơn thế nữa, nó chỉ ra lý do tại sao tài sản cá nhân định cư mở cửa cho các trạng thái không hợp lệ hoàn toàn không có biện pháp khắc phục để đảm bảo tính toàn vẹn của bất kỳ đối tượng nào cho phép trừu tượng bị rò rỉ. - Darrell Teague
"Đó là một đoạn mã đơn giản đẹp cho đến khi bạn nhận ra một setter" - hey, là bài viết gốc về Java hay về C #? :) - Honza Zidek
Tôi hoàn toàn đồng ý về khả năng đọc. Nó hoàn toàn rõ ràng những gì đang xảy ra khi person.name = "Joe"; được gọi là. Không có cruft trong cách của thông tin, cú pháp tô sáng cho thấy đó là một lĩnh vực và refactoring là đơn giản hơn (không cần phải refactor hai phương pháp và một lĩnh vực). Thứ hai, tất cả những chu kỳ não bị lãng phí đó suy nghĩ "getIsValid ()" hoặc nó nên là "isValid ()" vv có thể bị lãng quên. Tôi không thể nghĩ về một lần tôi đã được lưu từ một lỗi bởi một getter / setter. - Will


Có nhiều lý do. Yêu thích của tôi là khi bạn cần thay đổi hành vi hoặc điều chỉnh những gì bạn có thể đặt trên một biến. Ví dụ: giả sử bạn có phương thức setSpeed ​​(tốc độ int). Nhưng bạn muốn rằng bạn chỉ có thể đặt tốc độ tối đa là 100. Bạn sẽ làm điều gì đó như:

public void setSpeed(int speed) {
  if ( speed > 100 ) {
    this.speed = 100;
  } else {
    this.speed = speed;
  }
}

Bây giờ điều gì sẽ xảy ra nếu mọi thứ trong mã của bạn bạn đang sử dụng lĩnh vực công cộng và sau đó bạn nhận ra rằng bạn cần yêu cầu trên? Hãy vui vẻ săn lùng mọi cách sử dụng của lĩnh vực công cộng thay vì chỉ sửa đổi setter của bạn.

2 xu của tôi :)


43
2017-10-14 18:27



Săn lùng mọi cách sử dụng của lĩnh vực công cộng không phải là khó khăn. Làm cho nó riêng tư và để cho trình biên dịch tìm thấy chúng. - Nathan Fellman
đó là sự thật tất nhiên, nhưng tại sao làm cho nó khó hơn nó được thiết kế để được. Cách tiếp cận get / set vẫn là câu trả lời tốt hơn. - Hardryv
@Nathan: Phát hiện tập quán khác không phải là vấn đề. Thay đổi tất cả đều là. - Graeme Perrow
@GraemePerrow phải thay đổi tất cả là một lợi thế, không phải là một vấn đề: (Nếu bạn có mã giả định tốc độ có thể cao hơn 100 (bởi vì, bạn biết đấy, trước khi bạn phá vỡ hợp đồng, nó có thể!) (while(speed < 200) { do_something(); accelerate(); }) - R. Martinho Fernandes
Đó là một ví dụ rất tệ! Ai đó nên gọi: myCar.setSpeed(157); và sau vài dòng speed = myCar.getSpeed(); Và bây giờ ... tôi muốn bạn gỡ lỗi hạnh phúc trong khi cố gắng hiểu tại sao speed==100 khi nào nó nên 157 - Piotr Aleksander Chmielowski


Trong một getters và setters thế giới hướng đối tượng thuần túy là một khủng khiếp chống mô hình. Đọc bài viết này: Getters / Setters. Tà ác. Giai đoạn. Tóm lại, họ khuyến khích các lập trình viên suy nghĩ về các đối tượng như cấu trúc dữ liệu, và kiểu suy nghĩ này là thủ tục thuần túy (như trong COBOL hoặc C). Trong một ngôn ngữ hướng đối tượng không có cấu trúc dữ liệu, nhưng chỉ các đối tượng phơi bày hành vi (không phải thuộc tính / thuộc tính!)

Bạn có thể tìm hiểu thêm về họ trong Phần 3.5 của Đối tượng thanh lịch (cuốn sách của tôi về lập trình hướng đối tượng).


43
2017-09-23 16:39



Getters và setters đề xuất một mô hình miền thiếu máu. - Raedwald
Quan điểm thú vị. Nhưng trong hầu hết các bối cảnh lập trình, điều chúng ta cần là cấu trúc dữ liệu. Lấy ví dụ "Dog" của bài viết được liên kết. Có, bạn không thể thay đổi trọng lượng của một con chó trong thế giới thực bằng cách đặt thuộc tính ... nhưng new Dog() không phải là một con chó. Nó là đối tượng chứa thông tin về một con chó. Và đối với việc sử dụng đó, nó là tự nhiên để có thể sửa một trọng lượng ghi không chính xác. - Stephen C
@StephenC đó chính xác là cách ngôn ngữ thủ tục dạy chúng ta suy nghĩ. Tư duy đối tượng hoàn toàn ngược lại. Đối tượng không giữ thông tin về một con chó. Đối tượng là một chó. Cuốn sách này của tôi có thể giúp: Đối tượng thanh lịch - yegor256
Tôi đưa nó cho bạn phần lớn các chương trình hữu ích không cần phải mô hình / mô phỏng các đối tượng thế giới thực. IMO, điều này không thực sự là về ngôn ngữ lập trình. Đó là về những gì chúng tôi viết chương trình cho. - Stephen C
Thế giới thực hay không, yegor hoàn toàn đúng. Nếu những gì bạn có thực sự là một "Struct" và bạn không cần phải viết bất kỳ mã nào tham chiếu nó theo tên, hãy đặt nó trong một cấu trúc dữ liệu có thể Hashtable hoặc khác. Nếu bạn cần viết mã cho nó thì hãy đặt nó làm thành viên của một lớp và đặt mã điều khiển biến đó trong cùng một lớp và bỏ qua setter & getter. PS. mặc dù tôi chủ yếu chia sẻ quan điểm của yegor, tôi đã tin rằng các bean được chú thích không có mã là các cấu trúc dữ liệu hữu ích - cũng có thể là các getters đôi khi cần thiết, các setters không bao giờ tồn tại. - Bill K


Một ưu điểm của accessors và mutators là bạn có thể thực hiện xác nhận hợp lệ.

Ví dụ, nếu foo được công khai, tôi có thể dễ dàng đặt nó thành null và sau đó một người khác có thể cố gắng gọi một phương pháp trên đối tượng. Nhưng nó không còn ở đó nữa! Với một setFoo phương pháp, tôi có thể đảm bảo rằng foo chưa bao giờ được đặt thành null.

Accessors và mutators cũng cho phép đóng gói - nếu bạn không được thấy giá trị khi thiết lập của nó (có lẽ nó được đặt trong constructor và sau đó được sử dụng bởi các phương thức, nhưng không bao giờ được thay đổi), nó sẽ không bao giờ được nhìn thấy bởi bất cứ ai. Nhưng nếu bạn có thể cho phép các lớp khác xem hoặc thay đổi nó, bạn có thể cung cấp trình truy cập và / hoặc trình biến đổi thích hợp.


36
2017-10-14 18:25





Phụ thuộc vào ngôn ngữ của bạn. Bạn đã gắn thẻ "hướng đối tượng" thay vì "Java", vì vậy tôi muốn chỉ ra rằng câu trả lời của ChssPly76 là phụ thuộc vào ngôn ngữ. Ví dụ, trong Python, không có lý do gì để sử dụng getters và setters. Nếu bạn cần thay đổi hành vi, bạn có thể sử dụng một thuộc tính, kết thúc tốt nhất một trình thu thập và thiết lập xung quanh quyền truy cập thuộc tính cơ bản. Một cái gì đó như thế này:

class Simple(object):
   def _get_value(self):
       return self._value -1

   def _set_value(self, new_value):
       self._value = new_value + 1

   def _del_value(self):
       self.old_values.append(self._value)
       del self._value

   value = property(_get_value, _set_value, _del_value)

28
2017-10-14 18:32



Có, tôi đã nói nhiều như vậy trong một bình luận bên dưới câu trả lời của tôi. Java không phải là ngôn ngữ duy nhất để sử dụng getters / setters như một cái nạng giống như Python không phải là ngôn ngữ duy nhất có thể định nghĩa các thuộc tính. Điểm chính, tuy nhiên, vẫn còn - "tài sản" không phải là cùng một "lĩnh vực công cộng". - ChssPly76
@jcd - không hề. Bạn đang xác định "giao diện" của mình (API công khai sẽ là thuật ngữ tốt hơn ở đây) bằng cách hiển thị các trường công khai của bạn. Khi đã xong, sẽ không quay lại. Các thuộc tính KHÔNG phải là các trường vì chúng cung cấp cho bạn một cơ chế để chặn các nỗ lực truy cập các trường (bằng cách định tuyến chúng tới các phương thức nếu các phương thức đó được định nghĩa); đó là, tuy nhiên, không có gì nhiều hơn đường cú pháp trên phương thức getter / setter. Nó cực kỳ tiện lợi nhưng nó không làm thay đổi mô hình cơ bản - phơi bày các trường không kiểm soát truy cập vào chúng vi phạm nguyên tắc đóng gói. - ChssPly76
@ ChssPly76 — Tôi không đồng ý. Tôi có nhiều quyền kiểm soát như thể họ là tài sản, bởi vì tôi có thể làm cho họ bất động sản bất cứ khi nào tôi cần. Không có sự khác biệt giữa một thuộc tính sử dụng getters boilerplate và setters, và thuộc tính raw, ngoại trừ thuộc tính raw là nhanh hơn, bởi vì nó sử dụng ngôn ngữ cơ bản, thay vì gọi phương thức. Chức năng, chúng giống hệt nhau. Cách đóng gói duy nhất có thể bị vi phạm là nếu bạn nghĩ rằng dấu ngoặc đơn (obj.set_attr('foo')) vốn đã vượt trội so với dấu bằng (obj.attr = 'foo'). Truy cập công cộng là truy cập công cộng. - jcdyer
@jcdyer có nhiều quyền kiểm soát, nhưng không nhiều khả năng đọc, những người khác thường giả định sai obj.attr = 'foo' chỉ cần đặt biến mà không có bất kỳ điều gì khác xảy ra - Timo Huovinen
@TimoHuovinen Làm thế nào mà bất kỳ khác với một người sử dụng trong Java giả định rằng obj.setAttr('foo') "chỉ cần đặt biến mà không có bất cứ điều gì khác xảy ra"? Nếu đó là một phương thức công khai, thì đó là phương thức công khai. Nếu bạn sử dụng nó để đạt được một số tác dụng phụ, và nó là công khai, sau đó bạn đã tốt hơn có thể đếm trên tất cả mọi thứ làm việc như thể chỉ có tác dụng phụ dự kiến ​​đã xảy ra (với tất cả các các chi tiết triển khai khác và các tác dụng phụ khác, sử dụng tài nguyên, bất kỳ điều gì, bị ẩn khỏi các mối quan tâm của người dùng). Điều này hoàn toàn không khác với Python. Cú pháp của Python để đạt được hiệu ứng này đơn giản hơn. - ely