Mengapa variabel perlu tipe?

10

Jadi kami menulis:

Customer c = new Customer();

Mengapa desainnya tidak seperti yang kami tulis:

c = new Customer();
c.CreditLimit = 1000;

Kompiler dapat menghitung poin c untuk Pelanggan dan memungkinkan anggota Pelanggan dipanggil pada c?

Saya tahu kami mungkin ingin menulis:

IPerson c = new Customer();
IPerson e = new Employee();

sehingga dapat menulis:

public string GetName(IPerson object)
{
    return object.Name
}

string name = GetName(c); // or GetName(e);

Tetapi jika kita menulis:

c = new Customer();
e = new Employee();

kita masih bisa menulis:

public string GetName(object)
{
    return object.Name
}    

string name = GetName(c); // or GetName(e);

Kompiler dapat mengeluh tentang kode segera di atas jika jenis objek c referensi tidak mendukung properti Nama (karena dapat memeriksa anggota mana yang digunakan pada argumen / parameter dalam metode), atau runtime bisa mengeluh.

Bahkan dengan kata kunci dinamis C #, kami masih menggunakan variabel 'tipe' (ditentukan saat runtime). Tetapi mengapa suatu variabel membutuhkan tipe sama sekali? Saya yakin pasti ada alasan yang bagus, tetapi saya tidak bisa memikirkannya!

pohon kokoh
sumber
12
Inilah sebabnya mengapa ada bahasa dinamis seperti Python dan Ruby (dan lainnya). Tidak ada jawaban untuk pertanyaan ini. Itu fakta bahwa beberapa bahasa menggunakan deklarasi tipe dan beberapa bahasa tidak.
S.Lott
2
"variabel dalam bahasa tersebut tidak memiliki tipe sama sekali?" Benar. variabel tidak memiliki tipe dalam Python. Objek memiliki tipe dan variabel hanyalah referensi ke objek. Pertanyaan Anda benar-benar hanya sebuah pengamatan. Secara khusus "tidak semua bahasa memerlukan deklarasi variabel". Tidak ada jawaban. Jadi kemungkinan itu akan ditutup karena tidak konstruktif.
S.Lott
1
Anda mungkin ingin melihat Boo , yang memungkinkan Anda mendeklarasikan variabel tanpa deklarasi tipe apa pun, tetapi menggunakan inferensi tipe untuk mengetahui tipe sehingga Anda tidak mengorbankan manfaat ketepatan dan kinerja dari pengetikan yang kuat.
Mason Wheeler
2
var x = 1; - maksud Anda 32 bit, 64 bit, 16 bit? byte? mengapung? dua kali lipat? desimal? Ini hanya berurusan dengan primitif.
Pekerjaan
4
Anda dapat menggunakan vardalam C # dan menjadi eksotis di mana Anda ingin mendeklarasikan variabel selalu baik.
Daniel Little

Jawaban:

22

Tetapi mengapa suatu variabel membutuhkan tipe sama sekali?

  1. Ini mungkin menangkap bug di mana ekspresi yang salah dan diketik salah diberikan ke variabel. Beberapa bahasa memiliki pengetikan dinamis , yang mengorbankan jaminan ketepatan dari suatu jenis per variabel untuk jenis fleksibilitas yang Anda inginkan.
  2. Jenis memungkinkan kompiler untuk menghasilkan kode yang lebih efisien. Pengetikan dinamis berarti pemeriksaan jenis harus dilakukan saat runtime.
Fred Foo
sumber
1
Tolong jelaskan downvote.
Fred Foo
4
Juga, pengetikan dinamis datang pada biaya kinerja, karena informasi jenis perlu diperiksa selama runtime.
Charles Salvia
@CharlesSalvia: poin bagus, menambahkan itu ke jawabannya.
Fred Foo
2
@sturdytree: seperti untuk "jika tidak memiliki tipe, maka tidak dapat diketik salah" - sejauh aturan bahasa berjalan, itu benar. Tetapi variabel masih dapat diberi jenis yang salah dari sudut pandang semantik , misalnya Anda salah mengetik nama konstruktor dan program masih berjalan, tetapi tidak melakukan apa yang Anda inginkan.
Fred Foo
5
@sturdytree Meskipun benar bahwa tidak ada bahasa yang memiliki benar-benar typeless variabel dengan memeriksa jenis, ada bahasa yang memiliki inferensi tipe . Artinya, bahasa melihat penggunaan variabel Anda dan menyimpulkan jenis dari penggunaan Anda. Jika ada konflik (misalnya Anda melakukan a = new Bar()dan kemudian memanggil metode dari kelas Baz), kompiler menimbulkan kesalahan. Bahasa seperti Haskell dan OCaml memelopori inferensi tipe, tetapi hadir dalam C #, dengan varkata kunci.
quanticle
9

Anda memiliki titik yang benar-benar valid, bahasa yang tidak melacak tipe variabel yang ada, dan disebut "diketik secara dinamis". Kategori ini mencakup bahasa-bahasa seperti JavaScript, Perl, Lisp, dan Python.

Keuntungan yang kami dapatkan dari bahasa yang diketik secara statis adalah beberapa tambahan pengecekan waktu kompilasi.

Misalkan, misalnya, Anda memiliki metode berikut:

public addCustomerContact(Customer client, Employee contact) {
   ...
} 

Mungkin saja, jika Anda memiliki pelanggan bobdan karyawan jamesdalam kode Anda, untuk melakukan panggilan yang salah addCustomerContact(james, bob), yang tidak valid. Tetapi jika kompiler tidak mengetahui jenis variabel, itu tidak dapat memperingatkan Anda bahwa Anda telah membuat panggilan yang tidak valid, sebaliknya, kesalahan terjadi pada saat runtime ... dan karena bahasa yang diketik secara dinamis tidak memeriksa jenis parameter yang diteruskan ke metode, masalah itu terjadi setiap kali kode Anda mencoba menggunakan properti jamesobjek khusus pelanggan, atau properti khusus karyawan dari bobobjek. Itu mungkin lama setelah pasangan (james, bob) ditambahkan ke daftar kontak pelanggan.

Sekarang, Anda mungkin bertanya-tanya, mengapa kompiler tidak dapat menyimpulkan jenis jamesdan bob, dan masih memperingatkan kita? Itu kadang-kadang mungkin, tetapi jika variabel benar-benar tidak memiliki tipe, maka kita bisa melakukan hal berikut:

var james;
var bob;
if (getRandomNumber() > 0.5) {
   james = new Customer();
   bob = new Employee();
} else {
   james = new Employee();
   bob = new Customer();
}

Sangat sah untuk menetapkan nilai apa pun ke variabel apa pun, karena kami mengatakan variabel tidak memiliki tipe. Itu juga berarti kita tidak selalu bisa mengetahui tipe variabel, karena bisa dari tipe yang berbeda berdasarkan jalur eksekusi yang berbeda.

Secara umum, bahasa yang diketik secara dinamis digunakan untuk bahasa scripting, di mana tidak ada langkah kompilasi, sehingga kesalahan kompilasi tidak ada, artinya penekanan tombol tambahan yang diperlukan untuk memberikan tipe variabel tidak akan sangat berguna.

Ada beberapa keuntungan berbeda untuk bahasa yang diketik secara dinamis juga, sebagian besar dalam hal kode kurang diperlukan untuk mengimplementasikan desain yang sama: antarmuka tidak perlu ditulis, karena semuanya "diketik bebek" (kami hanya peduli metode / properti apa objek memiliki , bukan kelas milik objek), variabel tidak perlu diberi tipe eksplisit ... dengan trade off yang kami temukan tentang bug yang lebih sedikit sebelum kami mulai menjalankan kode kami.

Theodore Murdock
sumber
Terima kasih Theodore. "Tetapi jika kompiler tidak mengetahui jenis variabel, itu tidak dapat memperingatkan Anda bahwa Anda telah membuat panggilan tidak valid" Seperti yang Anda sebutkan, kompiler dapat mengetahui jenis objek yang ditunjuk variabel.
kokohtree
Theodore: Dalam contoh james / bob Anda, kita sebagai programmer harus tahu bagaimana kita telah menggunakan variabel kita (dan penamaan yang baik membantu) dan jadi saya tidak melihat masalah dengan itu. Ketika Anda mengatakan "kita tidak selalu dapat mengetahui jenis variabel" Saya berasumsi maksud Anda, kami tidak selalu dapat mengetahui jenis objek yang ditunjuk variabel, tetapi kompilator dapat menyelesaikannya dan memperingatkan tentang anggota yang salah diterapkan (yaitu kita dapat melakukan pemeriksaan statis).
kokohtree
2
Saya telah memberikan contoh di atas di mana Anda tidak dapat mengetahui jenis objek secara statis ... tergantung pada jalur eksekusi, jenis objek yang disimpan dalam variabel tanpa informasi jenis dapat berbeda. Anda dapat memiliki bahasa seperti C # di mana informasi jenis waktu kompilasi dapat disimpulkan, tetapi, sejauh yang saya tahu, tidak ada bahasa dengan kedua variabel jenis-pengecekan statis dan benar-benar tanpa tipe, kompleksitas komputasi analisis statis cenderung juga Bagus.
Theodore Murdock
Theodore, terima kasih, Anda sudah mengerti dengan benar bahwa apa yang saya bicarakan adalah bahasa dengan pemeriksaan tipe statis (berdasarkan jenis objek) dan variabel tanpa tipe. Sedih mendengar tidak ada - saya diberitahu Python memiliki variabel typeless, tetapi terdengar seperti itu tidak memiliki pemeriksaan tipe statis.
kokohtree
1
-1; pengetikan kuat / lemah adalah ortogonal ke pengetikan statis / dinamis. C diketik secara lemah lemah; Lisp dan Python keduanya diketik secara dinamis.
Fred Foo
5

Jadi programmer profesional tidak perlu mencari tahu apakah

10 + "10"

is "1010" or 20....

Apa itu kesalahan, pada waktu kompilasi dengan bahasa yang diketik secara statis atau waktu yang berjalan dengan yang diketik secara dinamis. Yang waras sih.

Tony Hopkinson
sumber
2
Yaitu, Perl bukan bahasa yang waras? :)
Fred Foo
5
@ Larsmans: sebenarnya, tidak, tidak. tapi itu murni opini.
NotMe
2
@ ChrisLively: Saya senang ini masalah fakta sekarang. Silakan datang ke tempat kerja saya kapan saja untuk meyakinkan rekan-rekan saya yang suka Perl;)
Fred Foo
2
10 + "10" menggunakan operator '+' pada objek tipe integer dan objek tipe string. Kompiler akan mengeluarkan kesalahan. Pertanyaan saya adalah hubungannya dengan jenis variabel, bukan objek.
kokohtree
2
Ini adalah valid C: itu ini aritmetik pointer.
dan04
4

Asumsikan Anda memiliki variabel one(set ke 1) dan berusaha untuk mengevaluasi one + one. Jika Anda tidak tahu jenis, maka 1 +1 akan ambigu. Anda dapat membantah bahwa 2 atau 11 bisa menjadi jawaban yang benar. Menjadi ambigu jika konteks tidak diberikan.

Saya telah melihat ini terjadi di SQLite di mana jenis-jenis basis data secara tidak sengaja diatur dan VARCHARbukannya INTketika operasi dilakukan orang mendapatkan hasil yang tidak terduga.

Dalam c # jika konteks menyimpulkan suatu jenis, Anda dapat menggunakan varkata kunci.

var c = new Customer();
var e = new Employer();

Akan mengkompilasi c dan e dengan tipe yang disimpulkan pada waktu kompilasi.

Stephen Quan
sumber
1
Dalam Python, 1 + 1selalu memiliki tipe int, tetapi tidak perlu menyatakan itu. Pertanyaannya adalah tentang mengapa variabel memiliki tipe, bukan nilai .
Fred Foo
Maaf Anda seharusnya variablestidak melihat valuesketika saya menggunakan 1 + 1dalam contoh saya. Saya kira itu tidak jelas.
Stephen Quan
Namun, bahasa yang diketik secara dinamis dapat menangani hal ini. Dalam Python, one=1; print(one+one)cetakan 2. one="1"; print(one+one)cetakan 11. Contoh SQLite lebih meyakinkan, tetapi masalahnya ada salah satu dari pengetikan yang lemah, jadi itu tidak benar-benar relevan dengan C #.
Fred Foo
Dalam skema yang saya sarankan, satu = 1 berarti variabel yang menunjuk ke tipe integer (saya tidak menyarankan tidak ada tipe sama sekali - objek akan memiliki tipe). satu + satu maka tidak akan ambigus (kami menambahkan dua objek / nilai integer)
kokohtree
1
Hai @ dan04, saya melihatnya dengan ORDER BYtidak sengaja dilakukan di VARCHARlapangan. Lihat stackoverflow.com/questions/9103313/… .
Stephen Quan
4

Variabel tidak perlu memiliki tipe terkait. Bahasa tempat ini benar termasuk Lisp, Skema, Erlang, Prolog, Smalltalk, Perl, Python, Ruby, dan lainnya.

Dimungkinkan juga untuk variabel untuk memiliki tipe, tetapi Anda mungkin tidak harus menuliskannya dalam program. Ini biasanya disebut inferensi tipe. ML, Haskell, dan keturunan mereka memiliki inferensi tipe yang kuat; beberapa bahasa lain memilikinya dalam bentuk yang lebih rendah, seperti autodeklarasi C ++ .

Argumen utama terhadap inferensi tipe adalah bahwa hal itu merusak keterbacaan. Biasanya lebih mudah untuk memahami kode ketika jenis dituliskan.

Ryan Culpepper
sumber
1

Saat Anda mengidentifikasi tipe yang diwakili variabel Anda, Anda membuat pernyataan tentang beberapa hal. Anda mengidentifikasi persyaratan alokasi memori untuk variabel Anda, dan Anda mendefinisikan kompatibilitas dan aturan kisaran untuk variabel Anda. Ini memberikan cara untuk menghindari kebingungan tentang niat Anda untuk data yang Anda simpan, dan untuk memberi Anda sarana yang relatif murah untuk mengidentifikasi potensi masalah dalam kode Anda pada waktu kompilasi.

Jika Anda mendeklarasikan variabel berikut:

myVar      = 5;
myOtherVar = "C";

Apa yang dapat Anda simpulkan tentang variabel-variabel ini? Apakah myVarditandatangani atau unsigned? Apakah 8-bit, 64-bit, atau sesuatu di antaranya? Apakah myOtherVarString (efektif array) atau Char? Apakah itu ANSI atau Unicode?

Dengan memasok tipe data tertentu, Anda memberikan petunjuk kepada kompiler tentang bagaimana ia dapat mengoptimalkan kebutuhan memori untuk aplikasi Anda. Beberapa bahasa tidak terlalu peduli dengan hal-hal semacam ini, memungkinkan hal-hal tersebut ditangani saat runtime, sementara bahasa lain akan memungkinkan sejumlah pengetikan dinamis karena dengan menganalisis kode, tipe data dapat disimpulkan.

Hal lain dengan bahasa yang sangat diketik, adalah itu menghemat Anda dari tidak perlu memberikan instruksi kepada kompiler setiap kali Anda menggunakan variabel. Bisakah Anda bayangkan betapa mengerikan dan tidak terbaca kode Anda akan menjadi jika setiap kali Anda mengakses variabel, Anda dipaksa untuk secara efektif melemparkannya untuk memberi tahu kompiler jenis nilai apa itu? !!

S.Robins
sumber
Poin bagus, walaupun kompiler hanya bisa menggunakan tipe paling efisien (mis. Int kecil) berdasarkan nilai, saya bisa melihat bahwa kita mungkin ingin "C" menjadi objek string daripada char sehingga dapat melakukan operasi tertentu . Namun dalam kasus-kasus seperti itu, kita cukup menentukan a = (string) "C". Ini menciptakan objek string dan 'a' (variabel yang tidak diketik) hanya menunjuk ke sana. Saya tidak melihat ini lebih mengerikan daripada string a = "C";
kokohtree
0

Program komputer adalah grafik node proses yang menggambarkan apa yang "mesin", diwakili oleh runtime bahasa (diperluas dengan toolkit dalam kebanyakan kasus) harus dilakukan, dalam urutan apa atau dalam kondisi apa. Grafik ini diwakili oleh file teks (atau sekelompok file teks) yang ditulis dalam bahasa tertentu, dan (sebagian atau seluruhnya) dibuat ketika kompiler / penerjemah membaca (deserialisasi) file ini. Selain itu, ada beberapa lingkungan (UML atau alat penghasil program grafis) tempat Anda dapat membuat grafik ini, dan menghasilkan kode sumber dalam bahasa target.

Mengapa saya mengatakan ini? Karena ini mengarah pada jawaban untuk pertanyaan Anda.

Teks program Anda adalah arahan Anda tentang bagaimana komputer harus menyelesaikan tugas yang sebenarnya, yang berisi langkah-langkah proses (kondisi, tindakan) DAN struktur (komponen apa yang Anda gunakan dalam solusi). Yang terakhir berarti bahwa Anda mendapatkan atau membuat beberapa instance komponen lain, memasukkannya ke dalam kotak bernama (variabel) dan menggunakannya: mengakses data dan layanan mereka.

Beberapa bahasa memberi Anda kotak seragam, di mana hanya label yang penting, tetapi Anda bisa memasukkan apa saja ke dalamnya, Anda bahkan dapat menggunakan variabel bernama "target" untuk menyimpan "Person" di awal dan "Car" di akhir algoritma yang sama. Yang lain mengharuskan Anda untuk membuat kotak "berbentuk", oleh karena itu kotak yang berbeda untuk Orang atau Mobil - meskipun mereka masih membiarkan Anda membuat "kotak generik" (Objek Java, C / C ++ batal *, Object C "id" ...) dan melemparkannya sesuka Anda. Bahasa yang diketik memungkinkan Anda mengekspresikan struktur Anda dalam detail yang lebih baik, menciptakan "ketik kontrak" untuk variabel Anda (meskipun Anda dapat meretas batasan ini), sementara bahasa yang tidak diketik mendukung ini "Saya pasti akan tahu apa yang telah saya masukkan ke dalam kotak itu kali ini" pendekatan sebagai perilaku default dan satu-satunya.

Kedua pendekatan itu layak, memiliki kecerdasan penyusunnya, banyak buku pemrograman, praktik, dan kerangka kerja yang ditulis menggunakannya (dan banyak buku lain tentang kerangka kerja itu) pada tingkat yang berbeda. Jadi hari ini jawabannya tampaknya lebih merupakan masalah selera dan pengetahuan tim programmer yang sebenarnya daripada pernyataan yang dibuat, diukur, dan diverifikasi tentang apakah akan menggunakan atau tidak menggunakan jenis.

Saya pikir tidak perlu mengatakan bahwa saya lebih suka aturan daripada trik, terutama untuk proyek-proyek tim besar (alias: "serius") jangka panjang. Alasan: sejauh yang saya tahu, kemungkinan besar penyebab kegagalan / slip proyek SW adalah: persyaratan tidak jelas dan desain buruk (80%! Menurut penelitian saya tahu), dan hanya beberapa persen yang tersisa untuk pengkodean aktual. Semua aturan dan kontrak menegakkan desain yang lebih bersih, berpikir ke depan, dan mengharuskan keputusan dibuat lebih awal dan oleh orang yang tepat. Jenis aturan berarti: kurang "kebebasan" dan "kesejukan" - lebih banyak persiapan, pemikiran, standar pengkodean, kerja tim yang terkontrol. Bagi saya, ini kedengarannya seperti faktor yang diperlukan untuk sukses, dan juga "rumah, rumah yang manis".

2 sen saya.

Lorand Kedves
sumber
-3

AFIAK semua bahasa dengan pengetikan dinamis adalah bahasa yang ditafsirkan. Itu sudah sangat tidak efisien, menambahkan ketidakefisienan pengetikan dinamis tidak akan menjadi kehilangan waktu yang besar. Namun, bahasa yang dikompilasi tidak akan benar-benar merujuk pada sesuatu dengan nama saat itu sedang berjalan. (Membatasi penggunaan refleksi .net atau fitur sejenisnya yang sangat lambat dibandingkan dengan bahasa yang mendasarinya.) Pencarian untuk semua nama itu akan menjadi lambat, lambat, lambat.

Loren Pechtel
sumber
3
Kamu tahu salah. Ada banyak kompiler untuk bahasa yang diketik secara dinamis, dan beberapa di antaranya cukup cepat. Contohnya termasuk Common Lisp, Scheme, dan Erlang.
Ryan Culpepper
3
Tidak ada yang namanya "bahasa yang ditafsirkan". Bahasa adalah seperangkat aturan matematika yang abstrak. Bahasa tidak dikompilasi atau diinterpretasikan. Bahasa apa adanya. Kompilasi dan interpretasi adalah ciri-ciri implementasi, bukan bahasa. Setiap bahasa dapat diimplementasikan dengan penerjemah, dan setiap bahasa dapat diimplementasikan dengan kompiler. Dan hampir semua bahasa memiliki implementasi yang ditafsirkan dan dikompilasi, misalnya ada penerjemah untuk C dan kompiler untuk ECMAScript, Ruby dan Python.
Jörg W Mittag
-4

Bahasa yang diketik secara dinamis sering disebut-sebut sebagai "berorientasi objek". Mereka tidak. Mereka mungkin berorientasi enkapsulasi, tetapi tidak pernah berorientasi objek. Orientasi objek adalah semua tentang tipe.

"Bocah itu mengendarai sepeda saudaranya ke toko kelontong dan membeli sepotong roti dari toko kelontong". Menggunakan orientasi objek, seseorang dapat langsung menulis sekumpulan kelas (tipe) untuk menggambarkan skenario dunia nyata ini.

Dalam bahasa yang diketik secara dinamis, skenario hanya dapat diwakili dengan demikian:

+ Msgstr "Objek mengendarai objek objeknya ke objek dan membeli objek dari objek".

Kekuatan orientasi objek adalah kemampuannya untuk memodelkan dunia dalam istilah alami, sehingga pengembang perangkat lunak dapat menggunakan kedua sisi otak untuk menulis perangkat lunak, dan memecahkan masalah lebih sebagai manusia, kurang sebagai programmer komputer. Kekuatan ini tidak ada dalam bahasa yang diketik secara dinamis.

Pengetikan statis memungkinkan efisiensi pengkodean yang lebih baik, kegunaan ulang, dan pemeliharaan, karena lingkungan pengembangan terintegrasi mengetahui jenis variabel. Mengetahui jenis variabel, sebuah IDE dapat menyediakan penyelesaian otomatis sehingga programmer tidak perlu merujuk kembali ke definisi kelas untuk mengingat apakah properti anggota dieja "backlightControl" atau "backLightControl" atau "bkLightCtrl".

Pengetikan statis memungkinkan refactoring otomatis, karena IDE tahu setiap tempat di mana variabel menyimpan instance dari objek yang sedang di-refactored.

Pengetikan statis memungkinkan usability dan maintainability yang lebih besar. Pengetikan dinamis lebih baik untuk kode sekali pakai. Misalkan pengembang baru keluar dari jalan, dan melihat potongan kode yang ada. Jika kode diketik secara statis, pengembang dapat, dengan dua klik mouse, memeriksa definisi kelas dari masing-masing variabel yang terlibat, tahu untuk apa kelasnya, mengetahui metode dan properti lain apa yang tersedia. Jika kode tersebut diketik secara dinamis, pengembang harus menggunakan pencarian global untuk mengetahui apa yang sedang terjadi.

Charlie Hand
sumber
2
Saya khawatir saya harus tidak setuju dengan Anda pada bagian pertama dari argumen Anda. Bahasa yang diketik secara dinamis biasanya "berorientasi objek", tetapi tidak "berorientasi kelas". Ini adalah perbedaan penting. Dalam contoh Anda, Anda sebenarnya hidup dalam ilusi. Anda mungkin memiliki Boykelas, tapi saya ragu itu bisa melakukan segalanya seperti yang dilakukan "bocah" dunia nyata. Namun, dalam contoh dinamis Anda (Objek naik ...), kami tahu satu-satunya hal penting tentang objek "anak laki-laki" ini - itu bisa naik . Itulah filosofi dasar bahasa tipe dinamis. Ini memiliki + ve s dan -ve s. Yang mana yang Anda sukai adalah opini Anda.
Chip