2010-04-30 39 views
26

Getters and Setters are badGetters and Setters là thiết kế OO kém?

Đọc nhanh qua bài viết trên tôi thấy rằng getters và setters là thiết kế OO kém và cần tránh khi chúng chống lại đóng gói và ẩn dữ liệu. Vì đây là trường hợp như thế nào nó có thể tránh được khi tạo ra các đối tượng và làm thế nào có thể một mô hình đối tượng để đưa điều này vào tài khoản.

Trong trường hợp yêu cầu thay thế hoặc thiết lập công cụ thay thế nào khác có thể được sử dụng?

Cảm ơn.

+0

Hãy xem http://stackoverflow.com/questions/565095/java-are-getters-and-setters-evil và câu trả lời được chấp nhận. –

+3

Bài viết thú vị nhưng -1 khi bài viết giải thích câu trả lời cho câu hỏi của bạn. –

+0

Đọc liên quan: http://c2.com/cgi/wiki?AccessorsAreEvil, http://c2.com/cgi/wiki?ForgetAboutWritingAccessors, http://c2.com/cgi/wiki?TellDontAsk – Seth

Trả lời

29

Getters hoặc setters của mình không phải là thiết kế OO xấu. Điều gì là xấu là thực hành mã hóa trong đó bao gồm một getter và một setter cho tất cả các thành viên duy nhất tự động, cho dù getter/setter là cần thiết hay không (cùng với việc công khai thành viên mà không nên công khai) - bởi vì điều này về cơ bản cho thấy lớp học 's thực hiện với thế giới bên ngoài vi phạm thông tin ẩn/trừu tượng. Đôi khi điều này được thực hiện tự động bởi IDE, có nghĩa là thực hành như vậy là phổ biến rộng rãi hơn nó hy vọng.

1

Tôi khuyên bạn nên đọc toàn bộ bài viết một cách cẩn thận vì nó trình bày những suy nghĩ và lựa chọn thay thế. Bản thân câu hỏi quá mở và câu trả lời bạn nhận được ở đây sẽ chỉ là ý kiến ​​nhiều hơn.

47

Bạn đã bỏ lỡ điểm. Bit hợp lệ, quan trọng của bài viết đó là:

Không yêu cầu thông tin bạn cần để thực hiện công việc; yêu cầu đối tượng có thông tin để thực hiện công việc cho bạn.

Khởi động theo kiểu Java và gia tăng setter là các triệu chứng bỏ qua lời khuyên này.

+4

Họ là một * có thể * triệu chứng. Nó cũng có thể là vấn đề chỉ đơn giản là không cho vay chính nó để được giải quyết theo cách đó.Hoặc chúng có thể là "triệu chứng" của việc sử dụng tiêm phụ thuộc. –

3

Cách tôi đọc nó, tác giả lập luận rằng một cách mù quáng đặt getters và setters xung quanh các lĩnh vực là không tốt hơn là chỉ làm cho lĩnh vực công cộng.

Tôi tin rằng tác giả lập luận rằng getters và setters nên được đặt thưa thớt, và cẩn thận, bởi vì ý tưởng của OO là các đối tượng nên hạn chế tiếp xúc với những gì chỉ cần thiết.

+0

Hơn nữa nhìn vào câu trả lời của Cory Petosky, nó chỉ là một cách xấu để xử lý thông tin. Nếu bạn đang yêu cầu một đối tượng để thực hiện một thao tác trên nó trên các biến bên trong, thì khi nào thì một setter hoặc getter đi vào hỗn hợp? –

5

Tôi tin rằng chỉ bao gồm những người định cư trong API nếu chúng thực sự là một phần của đặc tả lớp (nghĩa là hợp đồng với người gọi).

Bất kỳ thành viên dữ liệu khác liên quan đến đại diện bên trong phải được ẩn, và tôi thấy ít nhất 2 lý do chính cho rằng:

1) Nếu đại diện bên trong được tiếp xúc, thay đổi thiết kế là khá rắc rối trong tương lai, và đòi hỏi API cũng thay đổi.

2) Hiển thị thành viên dữ liệu với người định cư/getters mà không cần thận trọng cho phép người gọi hủy hoại sự bất biến của lớp học rất dễ dàng. Các đối tượng có trạng thái không nhất quán có thể gây ra các lỗi rất khó phân tích.

Thật không may có một số khung công tác khuyến khích (đôi khi yêu cầu) thêm bộ định cư/getters cho mọi thứ.

0

Từ bài viết:

Khi là một accessor được chứ? Đầu tiên, như tôi đã thảo luận trước đó, không sao cho phương thức trả về một đối tượng dưới dạng một giao diện mà đối tượng thực hiện vì giao diện đó tách biệt bạn khỏi các thay đổi đối với lớp thực hiện . Phương thức (trả về giao diện tham chiếu) không thực sự là "getter" trong ý nghĩa của phương thức chỉ cung cấp quyền truy cập vào một trường. Nếu bạn thay đổi việc thực hiện nội bộ của nhà cung cấp, bạn chỉ cần thay đổi định nghĩa của đối tượng trả về thành để đáp ứng các thay đổi. Bạn vẫn còn bảo vệ mã bên ngoài sử dụng đối tượng thông qua giao diện của nó.

Nói cách khác, hãy sử dụng giao diện cho cả hai phương thức getter và setter khi chúng cần thiết theo cách bạn có thể duy trì đóng gói. Đó là thực hành tốt nói chung để xác định một giao diện cho một kiểu trả về hoặc tham số chính thức.

+0

Đó là đồng bằng sai của bạn làm các lớp học công cụ nên phơi bày cấu hình của họ thông qua getters. –

2

Tôi sẽ tiến xa hơn một chút và chỉ nói các loại giá trị phải có getters. Mỗi loại giá trị sẽ không thay đổi và đi kèm với trình tạo hình có thể thay đổi và có trình cài đặt.

Nếu loại giá trị của bạn có bộ giải mã, chúng sẽ trả về một thể hiện mới sau khi sao chép các giá trị khác.

Url.setAnchor (...)

Sẽ trả về một Url mới sao chép cổng máy chủ, nhưng ghi đè lên neo.

Các loại lớp dịch vụ của bạn không cần các bộ định cư (đặt chúng trong ctor) và phông chữ chắc chắn cần phải có getters. Mailer của bạn nên lấy host/port/etc static stuff trong ctor của nó. Nếu tôi muốn gửi một email sau đó tôi di chuyển nó gửi(), không có lý do tại sao mã của tôi cần phải biết hoặc muốn hoặc yêu cầu máy chủ và các giá trị cấu hình khác. Điều đó nói rằng nó sẽ làm cho tinh thần để tạo ra một lớp MailServer như // kiểu giá trị MsilServer sau { Chuỗi chủ int cổng String username mật khẩu Strung // tất cả đến thu khí ruth } // nhà máy Mailer tạo (MailServer)

0

Có các bài viết khác cho biết chúng có thiết kế tốt. Nhưng câu trả lời là: getXXX và đặtXXX là tốt hoặc xấu dựa trên mức sử dụng. những toán học này làm cho rất nhiều thứ dễ dàng hơn. Vì vậy, nếu một số bài viết nói rằng đó là một thiết kế xấu tôi nghĩ; nó chỉ là cố gắng quá khó trên ý tưởng.

Một trong những cách sử dụng lớn nhất của các phương thức này có nhiều khuôn khổ và được sử dụng như một cơ chế phản ánh.

Vì vậy, đừng hoàn toàn tránh sử dụng những thứ này, thay vào đó ... hãy sử dụng nó một cách thận trọng.

nhờ Ayusman

0

Getters and Setters được thiết kế OO xấu?

Chỉ khi được sử dụng mà không suy nghĩ.

Nếu bạn tạo một đối tượng giá trị để truyền dữ liệu, chúng sẽ ổn.

Nếu bạn đang tạo một đối tượng quan trọng hơn thì chúng không nên ở đó. Hãy xem giao diện ArrayList* chẳng hạn. Bạn không thấy Object[] getElementData() vì điều đó sẽ phá vỡ đóng gói (một số có thể làm nóng mảng bên dưới).

* Im đề cập đến giao diện công cộng của lớp (các phương pháp tiếp xúc theo định nghĩa lớp)

0

Getters/setters là hoàn toàn phù hợp, trong điều kiện thích hợp. Tuy nhiên, khối lượng Get/Set là sai.

Tuy nhiên, tôi hơi bối rối. Bạn đã gắn thẻ Java nhưng tài liệu không thực sự đặc biệt là Java (chỉ các ví dụ). Cần lưu ý rằng trong C++ (được thực hiện tốt nhất trong 0x), nhiều vấn đề trong số này không tồn tại. Nếu bạn muốn thay đổi giao diện của mình từ dài thành int, thì giữa decltype, các mẫu và tự động điều này có thể dễ dàng đạt được, đó là lý do tại sao các cấu trúc như vậy bị đá. Typedef cũng hoạt động tốt.

1

Getters và setters chỉ là phương pháp. Họ làm gì? Họ thay đổi một lĩnh vực thành một tài sản, và đó là một sự khác biệt quan trọng.

Trường là một chút dữ liệu, trạng thái, trong đối tượng. Thuộc tính là một đặc tính quan sát được bên ngoài, một phần của hợp đồng của đối tượng. Phun ruột của một vật thể khắp nơi, cho dù trực tiếp hoặc thông qua getters/setters, luôn luôn là một ý tưởng tồi. Thiết kế kém. Nhưng nâng cao điều đó đến mức nói rằng getters và setters luôn xấu? Đó chỉ là một vài lập trình viên nghèo nàn mà không có cảm giác thích thú khi tuyên bố rằng quy tắc ngón tay cái mơ hồ (mà họ không thực sự hiểu ngay từ đầu) là luật gang.

Cá nhân, tôi có xu hướng cố gắng giữ tài sản như những thứ không thay đổi bất ngờ bên dưới chân của khách hàng. (Khách hàng của lớp đó là.) Các thuộc tính duy nhất mà tôi sẽ thay đổi động là những thuộc tính mà chúng không thể viết, và thậm chí sau đó tôi sẽ cố gắng tránh nó. Tôi cảm thấy rằng các thuộc tính có nhiều cách để kiểm soát hành vi của cá thể được thiết lập bởi máy khách, chứ không phải những thứ tùy ý dưới sự kiểm soát của lớp. (Đó là lĩnh vực bình thường dành cho ...)

4

Getters và setters không phải là xấu của mình. Điều xấu là thực hành làm cho bất kỳ lĩnh vực nào để được tư nhân và cung cấp getters/setters cho tất cả chúng không có vấn đề gì.

Các vấn đề liên quan