Tôi không nghĩ rằng có một câu trả lời bất khả tri về ngôn ngữ này vì câu hỏi cấu thành nên một tài sản ở thế giới là một câu hỏi dành riêng cho ngôn ngữ và những gì người gọi của một tài sản của người Hồi giáo cũng mong đợi là một câu hỏi dành riêng cho ngôn ngữ. Tôi nghĩ rằng cách hiệu quả nhất để nghĩ về điều này là suy nghĩ về những gì nó trông giống như từ quan điểm của người gọi.
Trong C #, các thuộc tính đặc biệt ở chỗ chúng (được quy ước) viết hoa (giống như các phương thức) nhưng thiếu dấu ngoặc đơn (như các biến thể hiện công khai). Nếu bạn thấy mã sau đây, tài liệu vắng mặt, bạn mong đợi điều gì?
var reciprocalHeading = myHeading.Reciprocal;
Là người mới làm quen với C #, nhưng một người đã đọc Nguyên tắc sử dụng tài sản của Microsoft , tôi sẽ mong đợi Reciprocal
, trong số những điều khác:
- là thành viên dữ liệu logic của
Heading
lớp
- không tốn kém để gọi, vì vậy tôi không cần phải lưu trữ giá trị
- thiếu tác dụng phụ có thể quan sát
- tạo ra kết quả tương tự nếu được gọi hai lần liên tiếp
- (có thể) cung cấp một
ReciprocalChanged
sự kiện
Trong số các giả định này, (3) và (4) có thể đúng (giả sử Heading
là loại giá trị bất biến, như trong câu trả lời của Ewan ), (1) không thể tranh cãi, (2) không rõ nhưng cũng không thể tranh cãi, và (5) không chắc có ý nghĩa ngữ nghĩa (mặc dù bất cứ điều gì có một tiêu đề có lẽ nên có một HeadingChanged
sự kiện). Điều này gợi ý cho tôi rằng trong API C #, không nên thực hiện hoặc tính toán đối ứng với nhau như một tài sản, mà đặc biệt là nếu phép tính rẻ và Heading
không thay đổi, đó là trường hợp đường biên.
(Tuy nhiên, xin lưu ý rằng không có bất kỳ mối quan tâm nào trong số những mối quan tâm này có liên quan đến việc gọi tài sản có tạo ra một thể hiện mới hay không, thậm chí (2). Tạo các đối tượng trong CLR, nói chung, là khá rẻ.)
Trong Java, các thuộc tính là một quy ước đặt tên phương thức. Nếu tôi thấy
Heading reciprocalHeading = myHeading.getReciprocal();
những kỳ vọng của tôi tương tự như những điều ở trên (nếu ít được đặt ra rõ ràng): Tôi hy vọng cuộc gọi sẽ rẻ, bình thường và thiếu tác dụng phụ. Tuy nhiên, bên ngoài khung công tác JavaBeans, khái niệm về một thuộc tính của Hồi không phải là tất cả có ý nghĩa trong Java và đặc biệt khi xem xét một thuộc tính bất biến không có tương ứng setReciprocal()
, getXXX()
quy ước hiện có phần lỗi thời. Từ Java hiệu quả , phiên bản thứ hai (đã hơn tám năm tuổi):
Các phương thức trả về một boolean
hàm không thuộc tính hoặc thuộc tính của đối tượng mà chúng được gọi thường được đặt tên bằng một danh từ, cụm danh từ hoặc cụm động từ bắt đầu bằng động từ get
. Có một đội ngũ phát biểu tuyên bố rằng chỉ có hình thức thứ ba (bắt đầu bằng get
) là có thể chấp nhận được, nhưng có rất ít cơ sở cho tuyên bố này. Hai hình thức đầu tiên thường dẫn đến mã dễ đọc hơn (trang 239)
Trong một API hiện đại, trôi chảy hơn, tôi sẽ thấy
Heading reciprocalHeading = myHeading.reciprocal();
- điều này một lần nữa gợi ý rằng cuộc gọi rẻ tiền, bình thường và thiếu tác dụng phụ, nhưng sẽ không nói gì về việc liệu một phép tính mới được thực hiện hay một đối tượng mới được tạo ra. Điều này là tốt; trong một API tốt, tôi không nên quan tâm.
Trong Ruby, không có thứ gọi là tài sản. Có những thuộc tính của người Viking, nhưng nếu tôi thấy
reciprocalHeading = my_heading.reciprocal
Tôi không có cách nào ngay lập tức để biết liệu tôi đang truy cập một biến đối tượng @reciprocal
thông qua một attr_reader
phương thức truy cập đơn giản hay liệu tôi đang gọi một phương thức thực hiện một phép tính đắt tiền. Thực tế, tên phương thức là một danh từ đơn giản, tuy nhiên, thay vì nói calcReciprocal
, một lần nữa, gợi ý rằng cuộc gọi ít nhất là rẻ và có lẽ không có tác dụng phụ.
Trong Scala, quy ước đặt tên là các phương thức có tác dụng phụ có dấu ngoặc đơn và phương thức mà không có chúng, nhưng
val reciprocal = heading.reciprocal
có thể là bất kỳ:
// immutable public value initialized at creation time
val reciprocal: Heading = …
// immutable public value initialized on first use
lazy val reciprocal: Heading = …
// public method, probably recalculating on each invocation
def reciprocal: Heading = …
// as above, with parentheses that, by convention, the caller
// should only omit if they know the method has no side effects
def reciprocal(): Heading = …
(Lưu ý rằng Scala cho phép nhiều thứ mà dù sao cũng không được hướng dẫn bởi phong cách . Đây là một trong những phiền toái lớn của tôi với Scala.)
Việc thiếu dấu ngoặc đơn cho tôi biết cuộc gọi không có tác dụng phụ; Tên, một lần nữa, gợi ý rằng cuộc gọi nên tương đối rẻ. Ngoài ra, tôi không quan tâm làm thế nào nó mang lại cho tôi giá trị.
Tóm lại: Biết ngôn ngữ bạn đang sử dụng và biết những kỳ vọng mà các lập trình viên khác sẽ mang lại cho API của bạn. Mọi thứ khác là một chi tiết thực hiện.
Heading
một kiểu bất biến vàreciprocal
trả lại một cái mớiHeading
là "hố thành công". (với lời cảnh báo ở hai cuộc gọireciprocal
sẽ trả về "cùng một thứ", tức là họ sẽ vượt qua bài kiểm tra về đẳng thức.)