Sự khác biệt giữa các tiền tố tên phương thức "đến" và "như" như thế nào
- liệt kê(),
- asList (),
- Vân vân...
Khi nào nên sử dụng khi thiết kế một phương pháp?
Sự khác biệt giữa các tiền tố tên phương thức "đến" và "như" như thế nào
Khi nào nên sử dụng khi thiết kế một phương pháp?
Câu trả lời:
Một toXYZ()
hàm được dự kiến sẽ thực hiện chuyển đổi và trả về một đối tượng độc lập mới (mặc dù tính bất biến cho phép tối ưu hóa, java.lang.String.toString()
chỉ trả về đối tượng).
Ví dụ, trong C ++, chúng ta có std::bitset::to_ulong()
thể dễ dàng thất bại và toàn bộ rất nhiều to_string()
, tất cả đều thực hiện chuyển đổi và phân bổ bộ nhớ phức tạp (ít nhiều).
asXYZ()
Mặt khác, một chức năng dự kiến sẽ trả về một khung nhìn (có khả năng khác nhau) của nguồn, thực hiện công việc tối thiểu.
Ví dụ, trong C ++, chúng ta có std::as_const()
trả về một tham chiếu không đổi và càng tham gia nhiều hơn std::forward_as_tuple
mà còn tham chiếu đến các đối số của nó bằng tham chiếu.
std::to_string(x)
tạo một đối tượng chuỗi mới, nhưng std::as_const(x)
tạo một tham chiếu (một khung nhìn) của đối tượng hiện có.
Thành thật mà nói, nó có thể chỉ là đặt tên không nhất quán. Nếu nhìn vào đối tượng thư viện chuẩn trong Smalltalk, ví dụ, tất cả các phương pháp mà làm "chuyển đổi phức tạp" hay "trở lại cơ quan đại diện đơn giản trong kiểu khác" được bắt đầu với as
, như trong asString
, asFloat
, asSeconds
, và các phương pháp tiêu chuẩn để chuyển đổi bất cứ điều gì để bất cứ điều gì khác, as: aClass
.
Trong Ruby, cùng loại của phương pháp được bắt đầu với to_
, như trong to_s
, to_a
, to_h
, viết tắt của string
, array
và hash
tương ứng.
Cả hai thư viện tiêu chuẩn dường như không phân biệt giữa các loại chuyển đổi khác nhau, có lẽ vì nó nên được coi là một chi tiết triển khai.
Tuy nhiên, trong Java chúng ta thấy rất nhiều sự pha trộn. Như bạn nói, có toString
, asList
và vân vân. Tôi tin rằng đây chỉ là một sự không nhất quán trong cách đặt tên, bởi vì nếu bạn cố gắng xác định một ý nghĩa khác nhau cho mỗi tiền tố, bạn sẽ luôn tìm thấy một ví dụ ngược lại ở một nơi khác trong thư viện chuẩn.
Vì vậy, trong mọi trường hợp, tôi muốn nói rằng điều quan trọng là bạn và nhóm của bạn chọn một tiền tố và sử dụng nó một cách nhất quán trong toàn bộ mã. Tính nhất quán là chìa khóa, vì vậy mọi người không được tự hỏi, giống như bạn phải làm.
toString
tạo một chuỗi mới bị ngắt kết nối hoàn toàn khỏi đối tượng (và không có cách nào khác vì tính bất biến). Các ví dụ tương tự, ví dụ, Collection#toArray
trong khi Arrays#asList
trả về một khung nhìn của mảng, được kết nối hai chiều (việc thay đổi mảng sẽ thay đổi danh sách và ngược lại). Vì vậy, nó khá nhất quán, mặc dù có thể có ngoại lệ. Chọn một tiền tố sẽ là sai. Nếu có Arrays#toList
, thì tôi hy vọng nó sẽ tạo ra một danh sách mới với một mảng bên dưới mới.
Mặc dù đã có một câu trả lời được chấp nhận, nó dường như tập trung vào C ++, trong khi câu hỏi được gắn thẻ java . Trong Java, ví dụ đầu tiên xuất hiện trong đầu cho loại điều này là Arrays.asList , trả về, về cơ bản, một khung nhìn của một mảng, được gói trong một danh sách. Các mảng cơ bản và danh sách vẫn được kết nối mặc dù; thay đổi đối với mảng được phản ánh trong danh sách và ngược lại. Tuy nhiên, mảng được trả về bởi phương thức toArray của danh sách độc lập với mảng ban đầu và từ danh sách:
String[] wordArray = {"one", "fine", "day"};
List<String> wordList = Arrays.asList(wordArray);
// changes to the array are visible in the list
System.out.println(wordList); // prints "[one, fine, day]"
wordArray[1] = "horrible";
System.out.println(wordList); // prints "[one, horrible, day]"
// changes to the list are visible in the array
wordList.set(1, "beautiful");
System.out.println(wordArray[1]); // prints "beautiful"
// but changes to the list or array don't affect the
// result from the list's toArray method.
String[] moreWords = wordList.toArray(new String[] {});
wordList.set(0, "the");
wordArray[1] = "best";
for (int i=0; i<3; i++) {
System.out.println(moreWords[i]); // prints "one", "beautiful", and "day"
}
Tất cả những gì đã nói, không có gì đảm bảo rằng mọi nhà phát triển thư viện đều tuân theo quy ước này, vì vậy bạn vẫn cần kiểm tra tài liệu để tìm hiểu xem đây có phải là hành vi bạn sẽ nhận được từ mã không xác định.
Một nơi khác mà tôi đã thấy là ... () phương thức được sử dụng thường xuyên là trong các kiểu hạ âm thành các kiểu phụ. Ví dụ: nếu bạn có một tập hợp các kiểu con, thì bạn có thể kết thúc bằng mã như:
/**
* Every Node is either an ANode or a BNode.
*/
interface Node {
/**
* Returns this Node as an ANode.
*
* @return this node
*/
default ANode asANode() {
if (this instanceof ANode) {
return (ANode) this;
}
else {
throw new UnsupportedOperationException();
}
// Or, in Java8 style, perhaps:
// return Optional.of(this)
// .filter(ANode.class::isInstance)
// .map(ANode.class::cast)
// .orElseThrow(UnsupportedOperationException::new);
}
/**
* Returns this Node as a BNode.
*
* @return this node
*/
default BNode asBNode() {
if (this instanceof BNode) {
return (BNode) this;
}
else {
throw new UnsupportedOperationException();
}
}
}
Sự khác biệt tôi nhận thấy (chỉ bây giờ bằng cách nghĩ về nó) là
Vì vậy, chúng tôi thấy AsInteger và AsString và chúng tôi thấy ToArray và ToStringList.
Để ngụ ý một chuyển đổi, có ý nghĩa (đó là một phong trào, một quá trình). Như ngụ ý một đại diện, một cách thể hiện đối tượng ban đầu.
Một cách nhìn khác về điều này:
Và sau đó là "nghệ thuật trước" (hoặc di sản) để giải quyết. Trước khi các ngôn ngữ hoàn toàn OO từ đầu, bạn sẽ có các hàm thư viện như StrToInt () và IntToStr (). Họ đã thực hiện chuyển đổi, họ là các hoạt động nên thật hợp lý khi gọi họ là SomethingToS Somethingelse (). Rốt cuộc, To hoạt động nhiều hơn As. Tôi đặc biệt nghĩ về Delphi ở đây.
Khi C # được thiết kế với tham vọng đi hết OO, sẽ có một phương thức trên đối tượng số nguyên bây giờ sẽ chuyển đổi số nguyên thành chuỗi. Mặc dù chúng ta cũng có một lớp Convert, việc chuyển đổi thành chuỗi rất phổ biến đến mức nó được tạo thành một phương thức ảo trên đối tượng. Các nhà thiết kế có thể đã hình dung rằng ToString sẽ quen thuộc hơn với mọi người từ mô hình cũ và có lẽ đây là lý do tại sao chúng ta có một phương thức ảo ToString () chứ không phải là một tài sản ảo AsString.
toString()
?