Apa perbedaan antara awalan nama metode "ke" dan "sebagai"? [Tutup]

78

Seperti apa perbedaan antara "to" dan "as" seperti awalan nama metode

  • toList (),
  • asList (),
  • dll ...

Kapan harus menggunakan yang mana ketika merancang suatu metode?

Daniel Hári
sumber

Jawaban:

120

Suatu toXYZ()fungsi diharapkan untuk melakukan konversi, dan untuk mengembalikan objek independen baru (meskipun ketidakmampuan memungkinkan untuk optimasi, java.lang.String.toString()hanya mengembalikan objek).
Sebagai contoh, di C ++ kami memiliki std::bitset::to_ulong()yang dapat dengan mudah gagal, dan sebagian besar dari to_string(), semua melakukan konversi kompleks (lebih atau kurang) dan mengalokasikan memori.

Sebuah asXYZ()fungsi di sisi lain diharapkan untuk mengembalikan (berpotensi berbeda) pandangan sumber, melakukan pekerjaan minimal.
Sebagai contoh, di C ++ kita memiliki std::as_const()yang hanya mengembalikan referensi konstan, dan lebih banyak terlibat std::forward_as_tupleyang juga merujuk argumennya dengan referensi.

Deduplicator
sumber
19
Ternyata ada beberapa preseden yang ada untuk ini. Secara umum, As [sesuatu] akan mirip dengan pemain, sedangkan To [sesuatu] membangun objek baru (dari jenis yang berbeda) dari yang sudah ada. Dalam kasus ToList, itu akan menjadi O (n) dan hampir pasti lebih mahal daripada "As." Lihat stackoverflow.com/questions/17968469/...
Robert Harvey
5
Itu bagian dari memilih nama deskriptif, dan bahkan jika perbedaan khusus ini tidak dikodifikasikan dalam standar pengkodean, melanggar itu melanggar Prinsip yang paling tidak mengejutkan .
Deduplicator
11
Saya akan menggambarkannya sebagai, secara naluriah, saya akan berpikir "menjadi" sebagai "berubah menjadi" dan "sebagai" sebagai "memperlakukan sebagai". Yang pertama berarti bekerja untuk mengubah hal itu, yang terakhir menyiratkan itu hanya perbedaan dalam bagaimana Anda bekerja dengannya.
Latty
6
Jika itu berarti sesuatu, itu harus berarti ini. Saya menyarankan bahwa itu sering tidak berarti apa-apa, jadi saya tidak akan bergantung pada kode pihak ketiga acak (tanpa melihat sesuatu di dokumen). Ini akan menjadi konvensi yang baik untuk diadopsi dalam basis kode.
Ben
4
Jawaban ini juga akurat dalam C ++: misalnya std::to_string(x)membuat objek string baru, tetapi std::as_const(x)membuat referensi (tampilan) dari objek yang ada.
Quuxplusone
13

Sejujurnya, itu mungkin hanya penamaan yang tidak konsisten. Jika di benda-benda perpustakaan standar di Smalltalk, misalnya, semua metode yang melakukan "kompleks konversi" atau "kembali representasi sederhana dalam jenis lain" yang diawali dengan as, seperti dalam asString, asFloat, asSeconds, dan metode standar untuk mengkonversi apa pun untuk hal lain, as: aClass.

Di Ruby, jenis yang sama dari metode yang diawali dengan to_, seperti dalam to_s, to_a, to_h, singkatan string, arraydan hashmasing-masing.

Tidak ada perpustakaan standar yang membedakan antara jenis konversi yang berbeda, mungkin karena itu harus dianggap sebagai detail implementasi.

Namun, di Jawa kami melihat banyak campuran. Seperti yang Anda sebutkan, ada toString, asListdan sebagainya. Saya percaya ini hanyalah inkonsistensi penamaan, karena jika Anda mencoba mendefinisikan arti yang berbeda untuk setiap awalan, Anda akan selalu menemukan contoh tandingan di tempat lain di pustaka standar.

Jadi dalam hal apa pun, saya akan mengatakan yang penting bagi Anda dan tim Anda untuk memilih satu awalan dan menggunakannya secara konsisten di seluruh kode. Konsistensi adalah kuncinya, sehingga orang tidak dibiarkan bertanya-tanya, seperti yang harus Anda lakukan.

MichelHenrich
sumber
1
Saya tidak percaya pada: memilih satu gaya untuk seluruh tim, melainkan memilih satu gaya untuk kasus serupa dalam modul, secara konsisten.
Daniel Hári
12
Di Jawa, toStringmembuat string baru terputus sepenuhnya dari objek (dan tidak ada cara lain karena kekekalan). Hal yang sama berlaku misalnya, untuk Collection#toArray, sambil Arrays#asListmengembalikan tampilan array, yang terhubung dua arah (mutasi array mengubah daftar dan sebaliknya). Jadi ini cukup konsisten, meskipun mungkin ada pengecualian. Memilih satu awalan akan salah. Jika ada Arrays#toList, maka saya berharap untuk membuat daftar baru dengan array yang mendasarinya baru.
maaartinus
Saya pikir Smalltalk hanya membuat kesalahan di sana, mereka tidak mengerti konvensi. Ini adalah konvensi yang sulit untuk dipahami (dan bahkan diperhatikan) karena sangat abstrak dan tidak terlalu berdampak. Bahkan tindakan menanyakan pertanyaan ini membutuhkan wawasan.
usr
3
@ usr Smalltalk mungkin telah dirancang sebelum menjadi konvensi
Bergi
6

Meskipun sudah ada jawaban yang diterima, tampaknya berfokus pada C ++, sementara pertanyaannya ditandai dengan java . Di Jawa, contoh pertama yang terlintas dalam pikiran untuk hal semacam ini adalah Arrays.asList , yang mengembalikan, pada dasarnya, tampilan array, terbungkus dalam daftar. Array yang mendasari dan daftar masih terhubung; perubahan array dicerminkan dalam daftar, dan sebaliknya. Namun, array yang dikembalikan oleh metode toArray daftar tidak tergantung dari array asli dan dari daftar:

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"
}

Semua yang dikatakan, tidak ada jaminan bahwa setiap pengembang perpustakaan mengikuti konvensi ini, jadi Anda masih perlu memeriksa dokumentasi untuk mengetahui apakah ini perilaku yang akan Anda dapatkan dari kode yang tidak dikenal.

Tempat lain yang saya lihat sebagai ... () metode yang sering digunakan adalah tipe downcasting ke sub-tipe. Misalnya, jika Anda memiliki satu set subtipe, maka Anda mungkin berakhir dengan kode seperti:

  /**
   * 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();
      }
    }
  }
Joshua Taylor
sumber
1

Perbedaan yang saya perhatikan (barusan dengan memikirkannya) adalah

  • Untuk biasanya mengkonversi ke tipe referensi yang berbeda (objek yang agak kompleks)
  • Seperti biasanya mengembalikan tipe nilai sederhana

Jadi kita melihat AsInteger dan AsString dan kita melihat ToArray dan ToStringList.

Untuk menyiratkan konversi, yang masuk akal (itu adalah gerakan, proses). Seperti menyiratkan representasi, cara mengekspresikan objek asli.

Cara lain untuk melihat ini:

  • To adalah operasi, jadi Anda akan menggunakannya untuk metode.
  • Seperti representasi sederhana, jadi Anda akan menggunakannya untuk properti.

Dan kemudian ada "prior art" (atau warisan) yang harus dihadapi. Sebelum bahasa sepenuhnya OO dari bawah ke atas, Anda akan memiliki fungsi perpustakaan seperti StrToInt () dan IntToStr (). Mereka melakukan konversi, mereka adalah operasi sehingga masuk akal untuk memanggil mereka SomethingToSomethingelse (). Bagaimanapun, To lebih aktif daripada As. Saya terutama berpikir tentang Delphi di sini.

Ketika C # dirancang dengan ambisi untuk menjalankan OO sepenuhnya, masuk akal untuk memiliki metode pada objek integer sekarang yang akan mengubah integer menjadi string. Meskipun kami juga memiliki kelas Konversi, konversi ke string sangat umum sehingga dibuat metode virtual pada objek. Para desainer mungkin berpikir bahwa ToString akan lebih akrab bagi orang-orang dari paradigma lama dan mungkin ini sebabnya kami mendapat metode virtual ToString () dan bukan properti virtual AsString.

Martin Maat
sumber
3
Bagaimana dengan toString()?
Deduplicator
Anda membuat saya di sana. Saya pikir AsString akan lebih tepat. Ibhave pemikiran tambahan, saya akan memperbarui jawaban saya.
Martin Maat
Saya tidak berpikir jawaban ini benar-benar mempengaruhi konvensi dalam C #. Misalnya. ToList () dan AsEnumerable () keduanya mengembalikan objek kompleks, perbedaannya adalah ToList () selalu mengembalikan objek baru sementara AsEnumerable () mengembalikan tampilan atau adaptor ke objek asli.
JacquesB
@JaquesB Rupanya ide yang berbeda telah diterapkan di sana-sini. Delphi memiliki properti AsInteger dan AsString pada objek TField (yang merangkum bidang database). Saya mungkin bias oleh ini. Tapi sekali lagi, pertanyaannya ditandai dengan Java, bukan dengan C # atau Delphi.
Martin Maat