Trước hết hãy rõ ràng về mô hình.
- Cấu trúc dữ liệu -> một bố cục của bộ nhớ có thể được duyệt và thao tác bằng các chức năng có kiến thức phù hợp.
- Đối tượng -> một mô-đun khép kín che giấu việc thực hiện và cung cấp giao diện có thể được truyền qua.
Một getter / setter hữu ích ở đâu?
Getters / Setters có hữu ích trong cấu trúc dữ liệu không? Không.
Cấu trúc dữ liệu là một đặc tả bố trí bộ nhớ phổ biến và được thao tác bởi một nhóm các hàm.
Nói chung, bất kỳ chức năng mới cũ nào cũng có thể xuất hiện và thao tác cấu trúc dữ liệu, nếu nó thực hiện theo cách mà các chức năng khác vẫn có thể hiểu được thì chức năng đó sẽ gia nhập gia đình. Nếu không, nó là một chức năng giả mạo và một nguồn lỗi.
Đừng hiểu sai ý tôi, có thể có một số họ chức năng cảnh báo về cấu trúc dữ liệu đó với snitches, áo khoác và tác nhân kép ở khắp mọi nơi. Thật tốt khi mỗi người có cấu trúc dữ liệu riêng để chơi, nhưng khi họ chia sẻ nó ... chỉ cần tưởng tượng một số gia đình tội phạm không đồng ý với chính trị, nó có thể trở thành một mớ hỗn độn rất nhanh.
Với các chức năng mở rộng lộn xộn mà các gia đình có thể đạt được, có cách nào để mã hóa cấu trúc dữ liệu để các hàm lừa đảo không làm rối tung mọi thứ? Vâng, chúng được gọi là Đối tượng.
Là getters / setters hữu ích trong các đối tượng? Không.
Toàn bộ vấn đề bao bọc một cấu trúc dữ liệu trong một đối tượng là để đảm bảo rằng không có chức năng giả mạo nào có thể tồn tại. Nếu chức năng muốn gia nhập gia đình, nó phải được xem xét kỹ lưỡng trước và sau đó trở thành một phần của đối tượng.
Điểm / mục đích của getter và setter là cho phép các hàm bên ngoài đối tượng thay đổi bố cục bộ nhớ của đối tượng trực tiếp. Nghe có vẻ như một cánh cửa mở để cho phép trong rogs ...
Vỏ máy
Có hai tình huống là một getter / setter công khai có ý nghĩa.
- Một phần của cấu trúc dữ liệu trong đối tượng được quản lý bởi đối tượng, nhưng không được đối tượng kiểm soát.
- Một giao diện mô tả sự trừu tượng hóa ở mức cao của cấu trúc dữ liệu trong đó một số phần tử được dự kiến sẽ không kiểm soát đối tượng thực hiện.
Container và giao diện container là ví dụ hoàn hảo cho cả hai tình huống này. Container quản lý các cấu trúc dữ liệu (danh sách liên kết, bản đồ, cây) bên trong nhưng bàn tay kiểm soát phần tử cụ thể cho tất cả và lặt vặt. Giao diện trừu tượng hóa điều này và bỏ qua việc thực hiện hoàn toàn và chỉ mô tả các kỳ vọng.
Thật không may, nhiều triển khai đã hiểu sai điều này và xác định giao diện của các loại đối tượng này để cấp quyền truy cập trực tiếp vào đối tượng thực tế. Cái gì đó như:
interface Container<T>
{
typedef ...T... TRef; //<somehow make TRef to be a reference or pointer to the memory location of T
TRef item(int index);
}
Nó bị hỏng. Việc triển khai Container phải rõ ràng trao quyền kiểm soát các phần bên trong của chúng cho bất kỳ ai sử dụng chúng. Tôi vẫn chưa thấy một ngôn ngữ có giá trị có thể thay đổi trong đó ngôn ngữ này tốt (các ngôn ngữ có ngữ nghĩa giá trị bất biến theo định nghĩa tốt từ góc độ tham nhũng dữ liệu, nhưng không nhất thiết từ góc độ gián điệp dữ liệu).
Bạn có thể cải thiện / sửa lỗi getters / setter bằng cách chỉ sử dụng ngữ nghĩa sao chép hoặc bằng cách sử dụng proxy:
interface Proxy<T>
{
operator T(); //<returns a copy
... operator ->(); //<permits a function call to be forwarded to an element
Proxy<T> operator=(T); //< permits the specific element to be replaced/assigned by another T.
}
interface Container<T>
{
Proxy<T> item(int index);
T item(int index); //<When T is a copy of the original value.
void item(int index, T new_value); //<where new_value is used to replace the old value
}
Có thể cho rằng một chức năng giả mạo vẫn có thể chơi tình trạng lộn xộn ở đây (với đủ nỗ lực hầu hết mọi thứ đều có thể), nhưng ngữ nghĩa sao chép và / hoặc proxy làm giảm cơ hội cho một số lỗi.
- tràn ra
- chảy tràn
- các tương tác với thành phần phụ là loại được kiểm tra / loại có thể kiểm tra được (trong các ngôn ngữ bị mất loại này là một lợi ích)
- Các yếu tố thực tế có thể hoặc không thể là cư dân bộ nhớ.
Getters / Setters riêng
Đây là pháo đài cuối cùng của getters và setters làm việc trực tiếp trên loại. Trong thực tế, tôi thậm chí sẽ không gọi những getters và setters này nhưng truy cập và thao tác.
Trong bối cảnh này, đôi khi thao túng một phần cụ thể của cấu trúc dữ liệu luôn luôn / hầu như luôn luôn / thường yêu cầu giữ sổ sách cụ thể để xảy ra. Giả sử khi bạn cập nhật thư mục gốc của cây, bộ đệm nhìn sang một bên cần phải được xóa hoặc khi bạn truy cập vào phần tử dữ liệu ngoài, cần phải lấy / giải phóng khóa. Trong những trường hợp này, nên áp dụng hiệu trưởng DRY và phân chia các hành động đó cùng nhau.
Trong bối cảnh riêng tư, các chức năng khác trong gia đình vẫn có thể thực hiện các bước 'getters và setters' này và thao tác cấu trúc dữ liệu. Do đó tại sao tôi nghĩ về họ nhiều hơn như là người truy cập và thao tác. Bạn có thể truy cập dữ liệu trực tiếp hoặc dựa vào một thành viên khác trong gia đình để có phần đó đúng.
Getters / Setters được bảo vệ
Trong một bối cảnh được bảo vệ, nó không quá khác biệt với bối cảnh công cộng. Các chức năng giả mạo nước ngoài có thể muốn truy cập vào cấu trúc dữ liệu. Vì vậy, không, nếu chúng tồn tại, chúng hoạt động như getters / setters công cộng.
this->variable = x + 5
hoặc gọi mộtUpdateStatistics
hàm trong setter và trong những trường hợp đóclassinstancea->variable = 5
sẽ gây ra vấn đề.