Kata new
kunci dalam bahasa seperti Java, Javascript, dan C # menciptakan instance baru dari sebuah kelas.
Sintaks ini tampaknya telah diwarisi dari C ++, di mana new
digunakan secara khusus untuk mengalokasikan instance baru dari kelas di heap, dan mengembalikan pointer ke instance baru. Dalam C ++, ini bukan satu-satunya cara untuk membangun objek. Anda juga dapat membuat objek di stack, tanpa menggunakan new
- dan pada kenyataannya, cara membangun objek ini jauh lebih umum di C ++.
Jadi, berasal dari latar belakang C ++, new
kata kunci dalam bahasa seperti Java, Javascript, dan C # tampak alami dan jelas bagi saya. Kemudian saya mulai belajar Python, yang tidak memiliki new
kata kunci. Dalam Python, sebuah instance dibangun hanya dengan memanggil konstruktor, seperti:
f = Foo()
Pada awalnya, ini terasa agak aneh bagi saya, sampai terlintas di benak saya bahwa tidak ada alasan bagi Python untuk memilikinya new
, karena semuanya adalah sebuah objek sehingga tidak perlu disatukan antara berbagai sintaks konstruktor.
Tapi kemudian saya berpikir - apa gunanya new
di Jawa? Kenapa kita harus bilang Object o = new Object();
? Kenapa tidak adil Object o = Object();
? Dalam C ++ pasti ada kebutuhan new
, karena kita perlu membedakan antara mengalokasikan di heap dan mengalokasikan di stack, tetapi di Jawa semua objek dibangun di heap, jadi mengapa bahkan memiliki new
kata kunci? Pertanyaan yang sama bisa ditanyakan untuk Javascript. Dalam C #, yang saya tidak terlalu kenal, saya pikir new
mungkin memiliki beberapa tujuan dalam hal membedakan antara tipe objek dan tipe nilai, tapi saya tidak yakin.
Bagaimanapun, menurut saya banyak bahasa yang muncul setelah C ++ hanya "mewarisi" new
kata kunci - tanpa benar-benar membutuhkannya. Ini hampir seperti kata kunci peninggalan . Kami tampaknya tidak membutuhkannya untuk alasan apa pun, namun itu ada di sana.
Pertanyaan: Apakah saya benar tentang ini? Atau ada beberapa alasan kuat yang new
perlu ada di C ++ - bahasa yang dikelola dengan memori yang diinspirasi seperti Java, Javascript dan C # tetapi tidak Python?
sumber
new
kata kunci. Tentu saja saya ingin membuat variabel baru, kompiler bodoh! Sebuah baik bahasa akan menurut saya memiliki sintaks sepertif = heap Foo()
,f = auto Foo()
.f
tidak luput dari fungsinya, alokasikan ruang stack.f
ketika fungsi melampirkan kembali.Jawaban:
Pengamatan Anda benar. C ++ adalah binatang yang rumit, dan
new
kata kunci itu digunakan untuk membedakan antara sesuatu yang dibutuhkandelete
kemudian dan sesuatu yang akan secara otomatis direklamasi. Di Jawa dan C #, mereka menjatuhkandelete
kata kunci karena pengumpul sampah akan mengurusnya untuk Anda.Masalahnya kemudian mengapa mereka menyimpan
new
kata kunci? Tanpa berbicara dengan orang-orang yang menulis bahasa itu agak sulit untuk dijawab. Tebakan terbaik saya tercantum di bawah ini:new
kata kunci membuat objek di heap. Jadi, mengapa mengubah perilaku yang diharapkan?Ruby berada di suatu tempat di antara Python dan Java / C # dalam penggunaannya
new
. Pada dasarnya Anda instantiate objek seperti ini:Itu bukan kata kunci, ini metode statis untuk kelas. Apa artinya itu adalah bahwa jika Anda menginginkan singleton, Anda dapat mengganti implementasi default
new()
untuk mengembalikan instance yang sama setiap waktu. Ini belum tentu direkomendasikan, tetapi itu mungkin.sumber
alloc
metode (kira-kira sama dengan Rubynew
) juga hanya metode kelas.Singkatnya, Anda benar. Kata kunci baru berlebihan dalam bahasa seperti Java dan C #. Berikut adalah beberapa wawasan dari Bruce Eckel yang merupakan anggota C ++ Standard Comitee pada 1990-an dan kemudian menerbitkan buku-buku tentang Jawa: http://www.artima.com/weblogs/viewpost.jsp?thread=260578
sumber
var
kunci sama sekali tidak sebagusauto
di C ++, tapi saya harap ini akan meningkat.Ada dua alasan yang bisa saya pikirkan:
new
membedakan antara objek dan primitifnew
sintaks sedikit lebih mudah dibaca (IMO)Yang pertama sepele. Saya pikir tidak sulit untuk membedakan keduanya. Yang kedua adalah contoh dari poin OP, yang
new
merupakan semacam redundan.Mungkin ada konflik namespace; mempertimbangkan:
Anda bisa, tanpa terlalu banyak imajinasi, dengan mudah berakhir dengan panggilan rekursif tanpa batas. Kompiler harus menegakkan kesalahan "Nama fungsi sama dengan objek". Ini benar-benar tidak ada salahnya, tetapi jauh lebih mudah digunakan
new
, yang menyatakan,Go to the object of the same name as this method and use the method that matches this signature.
Jawa adalah bahasa yang sangat sederhana untuk diurai, dan saya menduga ini membantu di daerah itu.sumber
Java, untuk satu, masih memiliki dikotomi C ++: tidak cukup segala sesuatu adalah obyek. Java memiliki tipe bawaan (mis.,
char
Danint
) yang tidak harus dialokasikan secara dinamis.Itu tidak berarti bahwa
new
itu benar-benar diperlukan di Jawa - set tipe yang tidak perlu dialokasikan secara dinamis adalah tetap dan diketahui. Ketika Anda mendefinisikan suatu objek, kompiler dapat mengetahui (dan, pada kenyataannya, memang tahu) apakah itu nilai sederhanachar
atau objek yang harus dialokasikan secara dinamis.Saya akan menahan diri (lagi-lagi) untuk tidak memberikan pendapat tentang apa artinya ini tentang kualitas desain Java (atau kekurangannya, seperti halnya).
sumber
new
, jadi ini bukan alasannya.Di JavaScript Anda membutuhkannya karena konstruktornya terlihat seperti fungsi normal, jadi bagaimana seharusnya JS tahu bahwa Anda ingin membuat objek baru jika bukan karena kata kunci baru?
sumber
Menariknya, VB memang membutuhkannya - perbedaan antara
yang mendeklarasikan variabel tanpa menugaskannya, setara dengan
Foo f;
dalam C #, danyang mendeklarasikan variabel dan memberikan instance baru dari kelas, yang setara dengan
var f = new Foo();
dalam C #, adalah perbedaan substantif. Di pre-.NET VB, Anda bahkan dapat menggunakanDim f As Foo
atauDim f As New Foo
- karena tidak ada kelebihan pada konstruktor.sumber
Dim f As Foo()
menyatakan sebuah array yang dariFoo
s. Oh sukacita! :-)Dim Foo As New Bar
akan secara efektif membuatFoo
properti yang akan membangun aBar
jika dibaca saat (yaituNothing
). Perilaku ini tidak terbatas terjadi sekali saja; pengaturanFoo
untukNothing
dan kemudian membacanya akan membuat yang baruBar
.Saya suka banyak jawaban dan hanya ingin menambahkan ini:
Itu membuat pembacaan kode lebih mudah
Bukan karena situasi ini akan sering terjadi, tetapi pertimbangkan Anda ingin metode dalam nama kata kerja yang berbagi nama yang sama dengan kata benda. C # dan bahasa lain secara alami memiliki kata
object
dilindungi undang-undang. Tetapi jika tidak maka akanFoo = object()
menjadi hasil dari pemanggilan metode objek atau akankah itu menjadi contoh objek baru. Semoga kata tanpanew
kata kunci memiliki perlindungan terhadap situasi ini, tetapi dengan memiliki persyaratannew
kata kunci sebelum memanggil konstruktor, Anda mengizinkan adanya metode dengan nama yang sama sebagai objek.sumber
Ada banyak hal peninggalan dalam banyak bahasa pemrograman. Kadang-kadang ada di sana dengan desain (C ++ dirancang agar kompatibel dengan mungkin dengan C), kadang-kadang, hanya ada Untuk contoh yang lebih mengerikan, pertimbangkan seberapa jauh
switch
pernyataan C yang rusak disebarkan.Saya tidak tahu Javascript dan C # cukup baik untuk mengatakan, tapi saya tidak melihat alasan
new
di Jawa kecuali bahwa C ++ memilikinya.sumber
x = new Y()
dalam JavaScript tidak instantiate yangY
kelas, karena JavaScript tidak memiliki kelas. Tapi sepertinya Java sehingga membawanew
kata kunci maju dari Jawa, yang tentu saja meneruskannya dari C ++.Dalam C # itu memungkinkan jenis terlihat dalam konteks di mana mereka mungkin dikaburkan oleh anggota. Ini memungkinkan Anda untuk memiliki properti dengan nama yang sama dengan tipenya. Pertimbangkan yang berikut ini,
Perhatikan penggunaan
new
memungkinkan untuk menjadi jelas bahwaAddress
iniAddress
bukan tipeAddress
anggota. Ini memungkinkan anggota untuk memiliki nama yang sama dengan tipenya. Tanpa ini, Anda perlu awalan nama jenis untuk menghindari tabrakan nama, sepertiCAddress
. Ini sangat disengaja karena Anders tidak pernah menyukai notasi hungaria atau yang serupa dan ingin C # dapat digunakan tanpa itu. Fakta itu juga akrab adalah bonus ganda.sumber
Menariknya, dengan munculnya penerusan yang sempurna, non-penempatan
new
juga tidak diperlukan di C ++. Jadi, bisa dibilang, itu tidak lagi diperlukan dalam bahasa yang disebutkan di atas.sumber
std::shared_ptr<int> foo();
harus meneleponnew int
.Saya tidak yakin apakah desainer Java mempertimbangkan hal ini, tetapi ketika Anda menganggap objek sebagai rekaman rekursif , maka Anda dapat membayangkan bahwa
Foo(123)
itu tidak mengembalikan objek tetapi fungsi yang fixpoint-nya adalah objek yang sedang dibuat (mis. Fungsi yang akan mengembalikan objek jika diberikan sebagai argumen objek yang sedang dibangun). Dan tujuannyanew
adalah untuk "mengikat simpul" dan mengembalikan fixpoint itu. Dengan kata lainnew
akan membuat "objek-to-be" sadar akan hal ituself
.Pendekatan semacam ini dapat membantu memformalkan pewarisan misalnya: Anda dapat memperluas fungsi-objek dengan fungsi-objek lain dan akhirnya memberikan mereka kesamaan
self
dengan menggunakannew
:Di sini
&
menggabungkan dua fungsi objek.Dalam hal ini
new
dapat didefinisikan sebagai:sumber
Untuk mengizinkan 'nihil'.
Seiring dengan alokasi berdasarkan tumpukan, Java menganut penggunaan objek nil. Bukan hanya sebagai artefak, tetapi sebagai fitur. Ketika objek dapat memiliki status nil, maka Anda harus memisahkan deklarasi dari inisialisasi. Maka kata kunci baru.
Dalam C ++ garis seperti
Akan langsung memanggil konstruktor default.
sumber
Person me = Nil
atau memilikiPerson me
menjadi Nil secara default dan menggunakanPerson me = Person()
untuk non-Nil? Maksud saya adalah bahwa sepertinya Nil bukan merupakan faktor dalam keputusan ini ...Person me
menjadi nihil danPerson me()
memanggil konstruktor default. Jadi, Anda akan selalu membutuhkan tanda kurung untuk memohon apa pun, dan dengan demikian menyingkirkan satu ketidakteraturan C ++.Alasan mengapa Python tidak membutuhkannya adalah karena sistem tipenya. Pada dasarnya, ketika Anda melihat
foo = bar()
dengan Python, tidak masalah apa punbar()
metode yang sedang dipanggil, kelas yang sedang dipakai, atau objek functor; dalam Python, tidak ada perbedaan mendasar antara functor dan fungsi (karena metode adalah objek); dan Anda bahkan bisa berdebat bahwa kelas yang dipakai adalah kasus khusus dari functor. Dengan demikian, tidak ada alasan untuk membuat perbedaan buatan dalam apa yang terjadi (terutama karena manajemen memori sangat tersembunyi di Python).Dalam bahasa dengan sistem pengetikan yang berbeda, atau di mana metode dan kelas bukan objek, ada kemungkinan perbedaan konseptual yang lebih kuat antara membuat objek dan memanggil fungsi atau functor. Jadi, bahkan jika kompiler / juru bahasa tidak memerlukan
new
kata kunci, dapat dimengerti bahwa itu dapat dipertahankan dalam bahasa yang belum melanggar semua batasan yang dimiliki Python.sumber
Sebenarnya di Jawa ada perbedaan saat menggunakan Strings:
berbeda dengan
Andaikan string
"myString"
tidak pernah digunakan sebelumnya, pernyataan pertama membuat objek String tunggal di kumpulan String (area khusus heap) sedangkan pernyataan kedua membuat dua objek, satu di area tumpukan normal untuk objek dan lainnya di string pool . Sangat jelas bahwa pernyataan kedua tidak berguna dalam skenario khusus ini, tetapi diizinkan oleh bahasa.Ini berarti bahwa baru menjamin bahwa objek dibuat di area khusus heap, dialokasikan untuk instantiasi objek normal, tetapi mungkin ada cara lain untuk instantiasi objek tanpa itu; yang di atas adalah contoh, dan ada ruang tersisa untuk diperpanjang.
sumber
String myString = String("myString");
?" (perhatikan tidak adanyanew
kata kunci)class MyClass { public MyClass() {} public MyClass MyClass() {return null;} public void doSomething { MyClass myClass = MyClass();}} //which is it, constructor or method?
String
bertentangan dengan konvensi gaya Java, jadi Anda bisa mengasumsikan metode apa pun yang dimulai dengan huruf besar adalah konstruktor. Dan kedua, jika kita tidak dibatasi oleh Java, maka Scala memiliki "kelas kasus" di mana konstruktornya terlihat persis seperti yang saya katakan. Jadi di mana masalahnya?new
untuk bahasa dikelola . Saya telah menunjukkan bahwanew
sama sekali tidak diperlukan (misalnya Scala tidak memerlukannya untuk kelas kasus) dan juga bahwa tidak ada ambiguitas (karena Anda benar-benar tidak dapat memiliki metode yang disebutkanMyClass
di kelasMyClass
). Tidak ada ambiguitas untukString s = String("hello")
; tidak mungkin hal lain selain konstruktor. Dan akhirnya, saya tidak setuju: konvensi kode ada untuk meningkatkan dan mengklarifikasi sintaksis, yang merupakan alasan Anda!new
kata kunci karena jika tidak sintaksis Java akan berbeda"? Saya yakin Anda dapat melihat kelemahan argumen itu;) Dan ya, Anda terus membahas sintaks, bukan semantik. Juga, kompatibilitas dengan apa? Jika Anda mendesain bahasa baru, seperti Java, Anda sudah tidak kompatibel dengan C dan C ++!Dalam C # baru penting untuk membedakan antara objek yang dibuat pada stack vs heap. Seringkali kita membuat objek pada stack untuk kinerja yang lebih baik. Lihat, ketika sebuah objek pada stack keluar dari ruang lingkup, ia langsung menghilang ketika stack terurai, seperti primitif. Tidak perlu bagi pengumpul sampah untuk melacaknya, dan tidak ada overhead tambahan dari manajer memori untuk mengalokasikan ruang yang diperlukan pada heap.
sumber