Thuộc tính so với phương thức


135

Câu hỏi nhanh: Khi nào bạn quyết định sử dụng các thuộc tính (trong C #) và khi nào bạn quyết định sử dụng các phương thức?

Chúng tôi đang bận rộn với cuộc tranh luận này và đã tìm thấy một số lĩnh vực mà nó đang tranh cãi liệu chúng ta nên sử dụng một tài sản hay một phương pháp. Một ví dụ là:

public void SetLabel(string text)
{
    Label.Text = text;
}

Trong ví dụ này, Labellà một điều khiển trên trang ASPX. Có một nguyên tắc có thể chi phối quyết định (trong trường hợp này) liệu biến nó thành phương pháp hay tài sản.

Tôi sẽ chấp nhận câu trả lời chung chung và toàn diện nhất, nhưng điều đó cũng chạm vào ví dụ mà tôi đã đưa ra.


2
-1 câu hỏi này đã được hỏi và trả lời trước: stackoverflow.com/questions/164527/NH
Element

Các ưu và nhược điểm của phương pháp / lĩnh vực / tài sản có thể tạo ra các cuộc tranh luận dài; Một số sử dụng chung cho các thuộc tính: khi bạn muốn các trường riêng tư / được bảo vệ nhưng đồng thời bạn muốn phơi bày chúng. Một cách sử dụng khác là không chỉ có các câu lệnh mà còn có các biểu thức (hành động nếu bạn muốn) thậm chí if()kiểm tra (theo MSDN). Nhưng điều này thật khó khăn vì người dùng không phải lúc nào cũng nhận thức được chi phí xử lý đằng sau việc truy cập một biến (thuộc tính) (tức là không có mã) và vì lý do nghiêm ngặt, người ta sẽ phải điểm chuẩn tài sản. Ồ, và một "phần thưởng" bạn không thể sử dụng con trỏ với các thuộc tính.
mireazma

Câu trả lời:


145

Từ phần Chọn giữa Thuộc tính và Phương thức của Nguyên tắc Thiết kế để Phát triển Thư viện Lớp:

Nói chung, các phương thức đại diện cho các hành động và các thuộc tính đại diện cho dữ liệu. Các thuộc tính có nghĩa là được sử dụng như các trường, có nghĩa là các thuộc tính không nên phức tạp về mặt tính toán hoặc tạo ra các tác dụng phụ. Khi nó không vi phạm các nguyên tắc sau, hãy xem xét sử dụng một thuộc tính, thay vì một phương thức, bởi vì các nhà phát triển ít kinh nghiệm tìm thấy các thuộc tính dễ sử dụng hơn.


3
Mặc dù tôi đồng ý với nhiều điều đó, tôi không nghĩ phần tác dụng phụ là đúng. Chẳng hạn, "Màu" thường là một thuộc tính của một đối tượng và nó có tác dụng phụ rõ ràng (thay đổi màu sắc của một đối tượng). Thay đổi thuộc tính có tác dụng phụ rõ ràng của việc thay đổi trạng thái đối tượng.
Erik Funkenbusch

46
Mystere Man thay đổi màu sắc là hiệu ứng mong muốn chứ không phải tác dụng phụ. Tác dụng phụ là một cái gì đó không được dự định trong hành động chính.
Muhammad Hasan Khan

2
@Mystere Man: việc thay đổi màu sắc không phải là một tác dụng phụ, tôi hoàn toàn đồng ý với câu trả lời này
Ahmed Said

2
"Bởi vì các nhà phát triển ít kinh nghiệm tìm thấy các thuộc tính dễ sử dụng hơn." - Theo tôi thấy đây là lý do duy nhất để lộ tài sản. Nhưng tôi có đúng không?
Tsabo

2
Sự khác biệt trong việc thực hiện nội bộ của một tài sản so với một phương pháp. Có bất cứ điều gì được đẩy vào ngăn xếp cuộc gọi bất cứ khi nào một tài sản được sử dụng? Nếu không, nó được xử lý như thế nào?
Praveen

57

Có, nếu tất cả những gì bạn đang làm là nhận và cài đặt, hãy sử dụng một thuộc tính.

Nếu bạn đang làm một cái gì đó phức tạp có thể ảnh hưởng đến một số thành viên dữ liệu, một phương pháp phù hợp hơn. Hoặc nếu getter của bạn lấy tham số hoặc setter của bạn mất nhiều hơn tham số giá trị.

Ở giữa là một khu vực màu xám, nơi đường kẻ có thể bị mờ đi một chút. Không có quy tắc cứng và nhanh và đôi khi những người khác nhau sẽ không đồng ý liệu thứ gì đó nên là tài sản hay phương pháp. Điều quan trọng là chỉ cần (tương đối) phù hợp với cách bạn làm điều đó (hoặc cách nhóm của bạn làm điều đó).

Chúng phần lớn có thể hoán đổi cho nhau nhưng một đặc tính báo hiệu cho người dùng rằng việc thực hiện tương đối "đơn giản". Oh và cú pháp là sạch hơn một chút.

Nói chung, triết lý của tôi là nếu bạn bắt đầu viết một tên phương thức bắt đầu bằng get hoặc set và lấy 0 hoặc một tham số (tương ứng) thì đó là một ứng cử viên chính cho một thuộc tính.


1
Bỏ phiếu. Điều này LAF không đúng. Độ phức tạp của getter hoặc setter được gói gọn trong mã getter / setter. Nó phức tạp đến mức nào không liên quan, cũng như nếu nó "ảnh hưởng đến một số thành viên dữ liệu" Đúng là một tham số không chuẩn hoặc nhiều tham số sẽ yêu cầu một phương thức, nhưng nếu không thì câu trả lời này không chính xác.
Hal50000

Câu đầu tiên giải thích tất cả. Bravo.
SWIIWII

13

Thuộc tính là một cách để tiêm hoặc lấy dữ liệu từ một đối tượng. Chúng tạo ra một sự trừu tượng hóa các biến hoặc dữ liệu trong một lớp. Chúng tương tự như getters và setters trong Java.

Các phương thức gói gọn một thao tác.

Nói chung, tôi sử dụng các thuộc tính để hiển thị các bit dữ liệu đơn lẻ hoặc các phép tính nhỏ trên một lớp, như thuế bán hàng. Được bắt nguồn từ số lượng mặt hàng và chi phí của chúng trong một giỏ hàng.

Tôi sử dụng các phương thức khi tôi tạo một hoạt động, như lấy dữ liệu từ cơ sở dữ liệu. Bất kỳ hoạt động có bộ phận di chuyển, là một ứng cử viên cho một phương pháp.

Trong ví dụ mã của bạn, tôi sẽ bọc nó trong một thuộc tính nếu tôi cần truy cập nó bên ngoài lớp chứa nó:

public Label Title 
{
   get{ return titleLabel;}
   set{ titleLabel = value;}
}

Đặt văn bản:

Title.Text = "Properties vs Methods";

Nếu tôi chỉ đặt thuộc tính Văn bản của Nhãn thì đây là cách tôi sẽ thực hiện:

public string Title 
{
   get{ return titleLabel.Text;}
   set{ titleLabel.Text = value;}
}

Đặt văn bản:

Title = "Properties vs Methods";

12

Nếu bạn đang đặt một thuộc tính thực tế của đối tượng thì bạn sử dụng một thuộc tính.

Nếu bạn đang thực hiện một nhiệm vụ / chức năng thì bạn sử dụng một phương pháp.

Trong ví dụ của bạn, nó là một thuộc tính xác định đang được đặt.

Tuy nhiên, nếu chức năng của bạn là AppendToLabel thì bạn sẽ sử dụng một phương thức.


11

Tìm kiếm thông qua MSDN, tôi tìm thấy một tài liệu tham khảo về Thuộc tính so với Phương thức cung cấp một số hướng dẫn tuyệt vời để tạo phương thức:

  • Các hoạt động là một chuyển đổi, chẳng hạn như Object.ToString.
  • Các hoạt động đủ tốn kém mà bạn muốn giao tiếp với người dùng mà họ nên xem xét lưu trữ kết quả.
  • Có được một giá trị thuộc tính bằng cách sử dụng bộ truy cập get sẽ có tác dụng phụ có thể quan sát được.
  • Gọi thành viên hai lần liên tiếp tạo ra kết quả khác nhau.
  • Trình tự thực hiện là quan trọng. Lưu ý rằng các thuộc tính của một loại sẽ có thể được thiết lập và truy xuất theo bất kỳ thứ tự nào.
  • Thành viên là tĩnh nhưng trả về một giá trị có thể thay đổi.
  • Các thành viên trả về một mảng. Các thuộc tính trả về mảng có thể rất sai lệch. Thông thường cần phải trả về một bản sao của mảng bên trong để người dùng không thể thay đổi trạng thái bên trong. Điều này, cùng với thực tế là người dùng có thể dễ dàng cho rằng đó là một thuộc tính được lập chỉ mục, dẫn đến mã không hiệu quả.

Tôi đồng ý rằng điều này có ý nghĩa bất cứ nơi nào áp dụng. Nhưng tôi có đúng không, rằng việc sử dụng các thuộc tính thông qua liên kết XAML trong WPF không có lựa chọn nào hơn là thực hiện các hành động thích hợp trong setter? (đặc biệt là một mục chọn mới cho ComboBox, ListBox, v.v.)
Nicolas

9

Bạn chỉ cần nhìn vào chính cái tên ... "Tài sản". Nó có nghĩa là gì? Từ điển định nghĩa nó theo nhiều cách, nhưng trong trường hợp này "một thuộc tính hoặc chất lượng thiết yếu hoặc đặc biệt của một thứ" phù hợp nhất.

Hãy suy nghĩ về mục đích của hành động. Trên thực tế, bạn có đang thay đổi hoặc truy xuất "một thuộc tính thiết yếu hoặc đặc biệt" không? Trong ví dụ của bạn, bạn đang sử dụng một hàm để đặt thuộc tính của hộp văn bản. Điều đó có vẻ ngớ ngẩn, phải không?

Thuộc tính thực sự là chức năng. Tất cả đều biên dịch thành getXXX () và setXXX (). Nó chỉ giấu chúng trong đường cú pháp, nhưng đó là đường cung cấp một ý nghĩa ngữ nghĩa cho quá trình.

Hãy suy nghĩ về các thuộc tính như thuộc tính. Một chiếc xe có nhiều thuộc tính. Màu sắc, MPG, Model, v.v. Không phải tất cả các thuộc tính đều có thể thiết lập được, một số thuộc tính có thể tính toán được.

Trong khi đó, một Phương pháp là một hành động. GetColor nên là một tài sản. GetFile () phải là một hàm. Một quy tắc khác là, nếu nó không thay đổi trạng thái của đối tượng, thì nó sẽ là một hàm. Ví dụ, CompatePiToNthDigit (n) phải là một hàm, vì nó không thực sự thay đổi trạng thái của đối tượng Math mà nó được đính kèm.

Điều này có thể lan man một chút, nhưng nó thực sự sôi sục khi quyết định đối tượng của bạn là gì và chúng đại diện cho cái gì. Nếu bạn không thể tìm ra nếu nó là một tài sản hoặc chức năng, có lẽ nó không thành vấn đề.


9

Thuộc tính đối xứng là thuộc tính của các đối tượng của bạn. Phương thức là hành vi của đối tượng của bạn.

Nhãn là một thuộc tính và nó có ý nghĩa hơn để biến nó thành một tài sản.

Về mặt lập trình hướng đối tượng, bạn nên hiểu rõ về đâu là một phần của hành vi và đâu chỉ là một thuộc tính.

Xe {Màu sắc, Mẫu mã, Thương hiệu}

Một chiếc xe có các thuộc tính Màu sắc, Kiểu và Thương hiệu do đó không có nghĩa là có phương thức SetColor hoặc SetModel vì về mặt thông thường, chúng tôi không yêu cầu Xe đặt màu riêng.

Vì vậy, nếu bạn ánh xạ trường hợp thuộc tính / phương thức vào đối tượng đời thực hoặc nhìn vào nó từ quan điểm tương quan, sự nhầm lẫn của bạn sẽ thực sự biến mất.


4

Ngoài ra điểm cộng lớn cho Properties là giá trị của thuộc tính có thể được nhìn thấy trong Visual Studio trong quá trình gỡ lỗi.


3

Tôi thích sử dụng các thuộc tính cho các phương thức add / set với 1 tham số. Nếu tham số nhiều hơn, sử dụng phương pháp.


3

Thuộc tính chỉ nên được thiết lập đơn giản và có được một lớp lót. Bất cứ điều gì nhiều hơn và nó thực sự nên được chuyển đến một phương pháp. Mã phức tạp phải luôn luôn trong các phương thức.


3

Tôi chỉ sử dụng các thuộc tính để truy cập biến, tức là nhận và đặt các biến riêng lẻ hoặc nhận và đặt dữ liệu trong các điều khiển. Ngay khi bất kỳ loại thao tác dữ liệu nào là cần thiết / được thực hiện, tôi sử dụng các phương thức.


3

Là một vấn đề của thiết kế Thuộc tính đại diện cho Dữ liệu hoặc Thuộc tính của đối tượng lớp, Trong khi các phương thức là hành động hoặc hành vi của đối tượng lớp.

Trong .Net, thế giới có những tác động khác của việc sử dụng Thuộc tính:

  • Các thuộc tính được sử dụng trong Databinding, trong khi các phương thức get_ / set_ thì không.
  • Thuộc tính người dùng tuần tự hóa XML như là cơ chế tự nhiên của serilization.
  • Các thuộc tính được truy cập bởi điều khiển PropertyGridICustomTypeDescriptor , có thể được sử dụng hiệu quả nếu bạn đang viết thư viện tùy chỉnh.
  • Các thuộc tính được kiểm soát bởi các thuộc tính , người ta có thể sử dụng nó một cách khôn ngoan để thiết kế các phần mềm hướng theo khía cạnh.

Những quan niệm sai lầm (IMHO) về việc sử dụng Thuộc tính:

  • Được sử dụng để hiển thị các phép tính nhỏ: Khối nhận của ControlDesigner.SelectionRules chạy thành 72 dòng !!
  • Được sử dụng để hiển thị cấu trúc dữ liệu nội bộ: Ngay cả khi một thuộc tính không ánh xạ tới thành viên dữ liệu nội bộ, người ta có thể sử dụng nó làm thuộc tính, nếu đó là một thuộc tính của lớp của bạn. Viceversa, ngay cả khi thuộc tính lớp của bạn không được khuyến khích, để trả về mảng như các thành viên dữ liệu (thay vào đó các phương thức được sử dụng để trả về bản sao sâu của các thành viên.)

Trong ví dụ ở đây, nó có thể đã được viết, với ý nghĩa kinh doanh nhiều hơn là:

public String Title
{
    set { Label.Text = text; }
}

2

Các thuộc tính thực sự tốt bởi vì chúng có thể truy cập được trong trình thiết kế hình ảnh của studio hình ảnh, miễn là chúng có quyền truy cập.

Chúng được sử dụng là bạn chỉ đơn thuần là thiết lập và nhận và có lẽ một số xác nhận không truy cập được một lượng mã đáng kể. Hãy cẩn thận vì tạo các đối tượng phức tạp trong quá trình xác nhận là không đơn giản.

Bất cứ phương pháp nào khác là cách ưa thích.

Nó không chỉ là về ngữ nghĩa. Sử dụng các thuộc tính không phù hợp bắt đầu có sự kỳ lạ xảy ra trong thiết kế hình ảnh phòng thu trực quan.

Chẳng hạn, tôi đã nhận được một giá trị cấu hình trong một thuộc tính của một lớp. Lớp cấu hình thực sự mở một tệp và chạy truy vấn sql để lấy giá trị của cấu hình đó. Điều này gây ra sự cố trong ứng dụng của tôi, nơi tệp cấu hình sẽ bị mở và khóa bởi chính studio hình ảnh thay vì ứng dụng của tôi vì không chỉ đọc mà còn ghi giá trị cấu hình (thông qua phương thức setter). Để khắc phục điều này tôi chỉ cần thay đổi nó thành một phương thức.


1

Dưới đây là một bộ hướng dẫn tốt về thời điểm sử dụng các thuộc tính so với các phương thức từ Bill Wagner

  • Sử dụng một tài sản khi tất cả những điều này là đúng: Các getters nên đơn giản và do đó không có khả năng đưa ra ngoại lệ. Lưu ý rằng điều này ngụ ý không có quyền truy cập mạng (hoặc cơ sở dữ liệu). Hoặc có thể thất bại, và do đó sẽ ném một ngoại lệ.
  • Họ không nên có sự phụ thuộc lẫn nhau. Lưu ý rằng điều này sẽ bao gồm thiết lập một thuộc tính và có ảnh hưởng đến một thuộc tính khác. (Ví dụ: đặt thuộc tính FirstName sẽ ảnh hưởng đến thuộc tính FullName chỉ đọc có chứa tên đầu tiên + thuộc tính tên cuối cùng ngụ ý một phụ thuộc như vậy)
  • Họ nên được giải quyết theo thứ tự bất kỳ
  • Trình getter không có tác dụng phụ có thể quan sát Lưu ý hướng dẫn này không loại trừ một số hình thức đánh giá lười biếng trong một tài sản.
  • Phương pháp phải luôn luôn quay trở lại ngay lập tức. (Lưu ý rằng điều này loại trừ một thuộc tính thực hiện cuộc gọi truy cập cơ sở dữ liệu, cuộc gọi dịch vụ web hoặc hoạt động tương tự khác).
  • Sử dụng một phương thức nếu thành viên trả về một mảng.
  • Các cuộc gọi lặp lại đến getter (không có mã can thiệp) sẽ trả về cùng một giá trị.
  • Các cuộc gọi lặp lại đến setter (có cùng giá trị) sẽ không mang lại sự khác biệt so với một cuộc gọi.

  • Việc nhận không nên trả về một tham chiếu đến các cấu trúc dữ liệu nội bộ (Xem mục 23). Một phương pháp có thể trả về một bản sao sâu và có thể tránh được vấn đề này.

* Lấy từ câu trả lời của tôi cho một câu hỏi trùng lặp.


Câu trả lời được xếp hạng và chấp nhận hàng đầu tại đây stackoverflow.com/a/1294189/1551 Tại sao downvote?
Chris Ballance

2
Tôi nhận ra rằng tôi đến bữa tiệc muộn một chút, nhưng điều đó rất có thể xảy ra do thực tế là bạn đã sao chép câu trả lời của mình. Bằng cách sao chép dán, bạn thừa nhận rằng câu hỏi này về cơ bản là một bản sao của câu hỏi khác. Như vậy, bạn nên đánh dấu nó là một bản sao thay vì trả lời nó. Tôi khuyên bạn nên xem một bài viết trên Meta để biết cách xử lý các câu hỏi trùng lặp.
Joshua

0

Cái này đơn giản.

1: sử dụng thuộc tính khi bạn muốn dữ liệu của bạn phải được xác thực trước khi lưu trữ trong trường. Vì vậy, theo cách này tài sản cung cấp đóng gói cho các lĩnh vực của bạn. Bởi vì nếu bạn để các trường của mình, người dùng cuối có thể gán bất kỳ giá trị nào có thể có hoặc không hợp lệ theo yêu cầu kinh doanh của bạn như tuổi nên lớn hơn 18. Vì vậy, trước khi giá trị là lưu trữ trường tương ứng, chúng ta cần kiểm tra tính hợp lệ của nó. Theo cách này các thuộc tính đại diện cho dữ liệu.

2: Sử dụng phương thức khi bạn muốn thực hiện một số hành động như bạn đang cung cấp một số dữ liệu dưới dạng tham số và phương thức của bạn đang thực hiện một số xử lý trên cơ sở các giá trị được cung cấp và trả về giá trị được xử lý làm đầu ra. Hoặc bạn muốn thay đổi giá trị của một số lĩnh vực bằng cách tính toán này. "Theo cách này, phương pháp đại diện cho hành động".


-1

Tôi đến từ java và tôi đã sử dụng phương thức get .. set .. trong một thời gian.

Khi tôi viết mã, tôi không tự hỏi: "truy cập dữ liệu này đơn giản hay đòi hỏi một quá trình nặng nề?" bởi vì mọi thứ có thể thay đổi (ngày nay lấy lại tài sản này là đơn giản, tomonrow có thể yêu cầu một số hoặc quá trình nặng nề).

Hôm nay tôi có một phương pháp SetAge (int age) tomonrow tôi cũng sẽ có phương thức SetAge (ngày sinh) tính tuổi bằng cách sử dụng ngày sinh.

Tôi đã rất thất vọng vì thuộc tính biến đổi trình biên dịch trong get và set nhưng không coi các phương thức Get ... và Set .. của tôi là như nhau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.