Apa yang dimaksud dengan "ketik aman"?
Apa yang dimaksud dengan "ketik aman"?
Jawaban:
Keamanan jenis berarti bahwa kompiler akan memvalidasi tipe saat mengkompilasi, dan melemparkan kesalahan jika Anda mencoba untuk menetapkan tipe yang salah ke variabel.
Beberapa contoh sederhana:
// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";
Ini juga berlaku untuk argumen metode, karena Anda memberikan tipe eksplisit kepada mereka:
int AddTwoNumbers(int a, int b)
{
return a + b;
}
Jika saya mencoba memanggilnya menggunakan:
int Sum = AddTwoNumbers(5, "5");
Compiler akan melempar kesalahan, karena saya meneruskan sebuah string ("5"), dan mengharapkan integer.
Dalam bahasa yang diketik secara longgar, seperti javascript, saya bisa melakukan hal berikut:
function AddTwoNumbers(a, b)
{
return a + b;
}
jika saya menyebutnya seperti ini:
Sum = AddTwoNumbers(5, "5");
Javascript secara otomatis mengonversi 5 menjadi string, dan mengembalikan "55". Ini disebabkan javascript menggunakan tanda + untuk rangkaian string. Untuk membuatnya sadar, Anda perlu melakukan sesuatu seperti:
function AddTwoNumbers(a, b)
{
return Number(a) + Number(b);
}
Atau, mungkin:
function AddOnlyTwoNumbers(a, b)
{
if (isNaN(a) || isNaN(b))
return false;
return Number(a) + Number(b);
}
jika saya menyebutnya seperti ini:
Sum = AddTwoNumbers(5, " dogs");
Javascript secara otomatis mengonversi 5 menjadi string, dan menambahkannya, untuk mengembalikan "5 anjing".
Tidak semua bahasa dinamis sama memaafkannya seperti javascript (Faktanya bahasa dinamis tidak secara implisit menyiratkan bahasa yang diketik longgar (lihat Python)), beberapa dari mereka benar-benar akan memberi Anda kesalahan runtime pada casting jenis yang tidak valid.
Meskipun nyaman, itu membuka Anda ke banyak kesalahan yang dapat dengan mudah dilewatkan, dan hanya diidentifikasi dengan menguji program yang sedang berjalan. Secara pribadi, saya lebih suka meminta kompiler memberitahu saya jika saya melakukan kesalahan itu.
Sekarang, kembali ke C # ...
C # mendukung fitur bahasa yang disebut kovarians , ini pada dasarnya berarti Anda dapat mengganti tipe dasar untuk tipe anak dan tidak menyebabkan kesalahan, misalnya:
public class Foo : Bar
{
}
Di sini, saya membuat kelas baru (Foo) yang mensubklasifikasikan Bar. Sekarang saya dapat membuat metode:
void DoSomething(Bar myBar)
Dan menyebutnya menggunakan Foo, atau Bar sebagai argumen, keduanya akan berfungsi tanpa menyebabkan kesalahan. Ini berfungsi karena C # tahu bahwa setiap kelas anak dari Bar akan mengimplementasikan antarmuka Bar.
Namun, Anda tidak dapat melakukan kebalikannya:
void DoSomething(Foo myFoo)
Dalam situasi ini, saya tidak bisa meneruskan Bar ke metode ini, karena kompiler tidak tahu bahwa Bar mengimplementasikan antarmuka Foo. Ini karena kelas anak dapat (dan biasanya akan) jauh berbeda dari kelas induknya.
Tentu saja, sekarang saya telah pergi jauh ke ujung dan melampaui ruang lingkup dari pertanyaan awal, tetapi semua hal yang baik untuk diketahui :)
Jenis keamanan tidak harus bingung dengan pengetikan statis / dinamis atau pengetikan kuat / lemah.
Bahasa tipe-aman adalah bahasa di mana satu-satunya operasi yang dapat dijalankan pada data adalah operasi yang dibenarkan oleh tipe data. Artinya, jika data Anda berjenis X
dan X
tidak mendukung operasi y
, maka bahasa tidak akan memungkinkan Anda untuk mengeksekusi y(X)
.
Definisi ini tidak menetapkan aturan kapan dicentang. Itu bisa pada waktu kompilasi (pengetikan statis) atau saat runtime (pengetikan dinamis), biasanya melalui pengecualian. Itu bisa sedikit dari keduanya: beberapa bahasa yang diketik secara statis memungkinkan Anda untuk melemparkan data dari satu jenis ke yang lain, dan validitas gips harus diperiksa pada saat runtime (bayangkan bahwa Anda mencoba untuk melemparkan Object
ke a Consumer
- kompilator tidak memiliki cara mengetahui apakah itu dapat diterima atau tidak).
Jenis-keamanan tidak selalu berarti sangat diketik, baik - beberapa bahasa terkenal diketik lemah, tetapi masih bisa dibilang tipe aman. Ambil Javascript, misalnya: sistem tipenya lemah karena datang, tetapi masih didefinisikan dengan ketat. Hal ini memungkinkan pencarian data secara otomatis (katakanlah, string ke int), tetapi dalam aturan yang jelas. Setahu saya tidak ada kasus di mana program Javascript akan berperilaku dengan cara yang tidak terdefinisi, dan jika Anda cukup pintar (saya tidak), Anda harus dapat memprediksi apa yang akan terjadi ketika membaca kode Javascript.
Contoh bahasa pemrograman tipe-tidak aman adalah C: membaca / menulis nilai array di luar batas array memiliki perilaku yang tidak ditentukan oleh spesifikasi . Tidak mungkin untuk memprediksi apa yang akan terjadi. C adalah bahasa yang memiliki sistem tipe, tetapi bukan tipe aman.
Keamanan jenis tidak hanya kendala waktu kompilasi, tetapi kendala waktu lari . Saya merasa bahkan setelah sekian lama, kita dapat menambahkan kejelasan lebih lanjut untuk ini.
Ada 2 masalah utama terkait dengan keamanan jenis. Memori ** dan tipe data (dengan operasi yang sesuai).
A char
biasanya membutuhkan 1 byte per karakter, atau 8 bit (tergantung pada bahasa, Java dan C # store unicode chars yang membutuhkan 16 bit). Sebuah int
membutuhkan 4 byte, atau 32 bit (biasanya).
Secara visual:
char: |-|-|-|-|-|-|-|-|
int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
Jenis bahasa yang aman tidak memungkinkan int untuk dimasukkan ke dalam char pada saat run-time (ini harus membuang beberapa jenis pemeran kelas atau keluar dari memori). Namun, dalam jenis bahasa yang tidak aman, Anda akan menimpa data yang ada dalam 3 byte memori yang lebih berdekatan.
int >> char:
|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|
Dalam kasus di atas, 3 byte di sebelah kanan ditimpa, sehingga setiap petunjuk ke memori itu (katakanlah 3 karakter berturut-turut) yang diharapkan untuk mendapatkan nilai char yang dapat diprediksi sekarang akan memiliki sampah. Hal ini menyebabkan undefined
perilaku di program Anda (atau lebih buruk, mungkin di program lain tergantung pada bagaimana OS mengalokasikan memori - sangat tidak mungkin hari ini).
** Meskipun masalah pertama ini bukan tentang tipe data secara teknis, ketik bahasa aman mengatasinya secara inheren dan secara visual menjelaskan masalah ini kepada mereka yang tidak mengetahui bagaimana alokasi memori "terlihat".
Masalah tipe lebih halus dan langsung adalah di mana dua tipe data menggunakan alokasi memori yang sama. Ambil int vs int yang tidak ditandatangani. Keduanya 32 bit. (Dengan mudah bisa menjadi char [4] dan int, tetapi masalah yang lebih umum adalah uint vs int).
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
Suatu jenis bahasa yang tidak aman memungkinkan programmer untuk mereferensikan rentang 32 bit yang dialokasikan dengan benar, tetapi ketika nilai int yang tidak ditandatangani dibaca ke dalam ruang int (atau sebaliknya), kita kembali memiliki undefined
perilaku. Bayangkan masalah yang dapat ditimbulkannya dalam program perbankan:
"Sobat! Saya cerdik $ 30 dan sekarang saya punya $ 65.506 tersisa !!"
... tentu saja, program perbankan menggunakan tipe data yang jauh lebih besar. ;) LOL!
Seperti yang telah ditunjukkan orang lain, masalah berikutnya adalah operasi komputasi pada jenis. Itu sudah cukup tertutup.
Sebagian besar programmer saat ini tidak perlu khawatir tentang hal-hal seperti itu kecuali mereka menggunakan sesuatu seperti C atau C ++. Kedua bahasa ini memungkinkan pemrogram untuk dengan mudah melanggar keamanan jenis pada waktu berjalan (referensi memori langsung) meskipun upaya terbaik kompiler untuk meminimalkan risiko. NAMUN, ini tidak semuanya buruk.
Salah satu alasan mengapa bahasa ini sangat cepat secara komputasi adalah karena mereka tidak terbebani dengan memverifikasi kompatibilitas tipe selama operasi run time seperti, misalnya, Java. Mereka menganggap pengembang adalah makhluk rasional yang baik yang tidak akan menambahkan string dan int bersama-sama dan untuk itu, pengembang dihargai dengan kecepatan / efisiensi.
Banyak jawaban di sini mengacaukan keamanan jenis dengan pengetikan statis dan pengetikan dinamis. Bahasa yang diketik secara dinamis (seperti smalltalk) juga dapat mengetik dengan aman.
Jawaban singkat: bahasa dianggap aman-tipe jika tidak ada operasi yang mengarah ke perilaku yang tidak terdefinisi. Banyak yang menganggap persyaratan konversi jenis eksplisit yang diperlukan untuk suatu bahasa diketik dengan ketat , karena konversi otomatis terkadang dapat mengarah ke perilaku yang didefinisikan dengan baik tetapi tidak terduga / tidak intuitif.
if no operation leads to undefined behavior
.
Penjelasan dari jurusan seni liberal, bukan jurusan ilmiah:
Ketika orang mengatakan bahwa bahasa atau fitur bahasa adalah tipe aman, artinya bahasa tersebut akan membantu mencegah Anda, misalnya, meneruskan sesuatu yang bukan bilangan bulat ke logika yang mengharapkan bilangan bulat.
Misalnya, dalam C #, saya mendefinisikan suatu fungsi sebagai:
void foo(int arg)
Kompiler akan menghentikan saya melakukan hal ini:
// call foo
foo("hello world")
Dalam bahasa lain, kompiler tidak akan menghentikan saya (atau tidak ada kompiler ...), jadi string akan diteruskan ke logika dan kemudian mungkin sesuatu yang buruk akan terjadi.
Ketik bahasa aman mencoba menangkap lebih banyak di "waktu kompilasi".
Di sisi bawah, dengan mengetikkan bahasa yang aman, ketika Anda memiliki string seperti "123" dan Anda ingin mengoperasikannya seperti int, Anda harus menulis lebih banyak kode untuk mengubah string ke int, atau ketika Anda memiliki int suka 123 dan ingin menggunakannya dalam pesan seperti, "Jawabannya 123", Anda harus menulis lebih banyak kode untuk mengonversi / membuangnya ke string.
Untuk mendapatkan pemahaman yang lebih baik, tonton video di bawah ini yang menunjukkan kode dalam bahasa aman (C #) dan TIDAK ketik bahasa aman (javascript).
http://www.youtube.com/watch?v=Rlw_njQhkxw
Sekarang untuk teks panjang.
Keamanan jenis berarti mencegah kesalahan tipe. Kesalahan tipe terjadi ketika tipe data dari satu tipe ditugaskan ke tipe lain tanpa tahu dan kami mendapatkan hasil yang tidak diinginkan.
Misalnya JavaScript adalah BUKAN jenis bahasa yang aman. Dalam kode di bawah ini "num" adalah variabel numerik dan "str" adalah string. Javascript memungkinkan saya melakukan "num + str", sekarang GUESS akan melakukan aritmatika atau penggabungan.
Sekarang untuk kode di bawah ini hasilnya "55" tetapi yang penting adalah kebingungan yang dibuat seperti apa operasi yang akan dilakukan.
Ini terjadi karena javascript bukan jenis bahasa yang aman. Memungkinkan untuk mengatur satu tipe data ke tipe lainnya tanpa batasan.
<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays “55”
</script>
C # adalah jenis bahasa yang aman. Itu tidak memungkinkan satu tipe data untuk ditugaskan ke tipe data lainnya. Kode di bawah ini tidak memungkinkan operator "+" pada tipe data yang berbeda.
Jenis-aman berarti bahwa secara terprogram, jenis data untuk suatu variabel, nilai balik, atau argumen harus sesuai dengan kriteria tertentu.
Dalam prakteknya, ini berarti bahwa 7 (tipe integer) berbeda dari "7" (karakter tipe string yang dikutip).
PHP, Javascript, dan bahasa skrip dinamis lainnya biasanya diketik dengan lemah, karena mereka akan mengonversi (string) "7" menjadi (integer) 7 jika Anda mencoba menambahkan "7" + 3, meskipun kadang-kadang Anda harus melakukan ini secara eksplisit (dan Javascript menggunakan karakter "+" untuk concatenation).
C / C ++ / Java tidak akan mengerti itu, atau akan menggabungkan hasilnya menjadi "73". Keamanan tipe mencegah tipe bug ini dalam kode dengan membuat persyaratan tipe eksplisit.
Jenis keamanan sangat berguna. Solusi untuk "7" + 3 di atas adalah dengan mengetikkan cor (int) "7" + 3 (sama dengan 10).
Konsep:
Untuk menjadi Type Safe sangat sederhana seperti artinya, itu memastikan bahwa tipe variabel harus aman seperti
jadi ini semua tentang keamanan jenis penyimpanan Anda dalam hal variabel.
Coba penjelasan ini pada ...
TypeSafe berarti bahwa variabel diperiksa secara statis untuk tugas yang sesuai pada waktu kompilasi. Sebagai contoh, buat string atau bilangan bulat. Dua tipe data yang berbeda ini tidak dapat ditugaskan silang (yaitu, Anda tidak dapat menetapkan integer ke string atau Anda tidak dapat menetapkan string ke integer).
Untuk perilaku yang tidak aman, pertimbangkan ini:
object x = 89;
int y;
jika Anda mencoba melakukan ini:
y = x;
kompiler melempar kesalahan yang mengatakan itu tidak dapat mengkonversi System.Object ke Integer. Anda perlu melakukannya secara eksplisit. Salah satu caranya adalah:
y = Convert.ToInt32( x );
Tugas di atas tidak aman untuk mengetik. Penugasan typesafe adalah tempat tipe-tipe tersebut dapat secara langsung ditugaskan satu sama lain.
Koleksi non typesafe berlimpah di ASP.NET (mis., Koleksi aplikasi, sesi, dan kondisi tampilan). Kabar baiknya tentang koleksi ini adalah bahwa (meminimalkan beberapa pertimbangan manajemen status server), Anda dapat menempatkan hampir semua jenis data di salah satu dari tiga koleksi. Berita buruknya: karena koleksi ini bukan jenis huruf yang aman, Anda harus memberikan nilai secara tepat saat Anda mengambilnya kembali.
Sebagai contoh:
Session[ "x" ] = 34;
bekerja dengan baik. Tetapi untuk menetapkan kembali nilai integer, Anda harus:
int i = Convert.ToInt32( Session[ "x" ] );
Baca tentang obat generik untuk mengetahui fasilitas yang membantu Anda dengan mudah mengimplementasikan koleksi typesafe.
C # adalah bahasa yang aman untuk mengetik tetapi perhatikan artikel tentang C # 4.0; kemungkinan dinamis yang menarik tenun (apakah itu hal yang baik bahwa C # pada dasarnya mendapatkan Option Strict: Off ... kita akan lihat).
Jenis-Aman adalah kode yang hanya mengakses lokasi memori yang diizinkan untuk diakses, dan hanya dengan cara yang jelas dan diizinkan. Kode jenis-aman tidak dapat melakukan operasi pada objek yang tidak valid untuk objek itu. Kompiler bahasa C # dan VB.NET selalu menghasilkan kode tipe-aman, yang diverifikasi menjadi tipe-aman selama kompilasi JIT.
Jenis-aman berarti bahwa set nilai yang dapat ditetapkan ke variabel program harus sesuai dengan kriteria yang jelas dan dapat diuji. Variabel tipe-aman mengarah ke program yang lebih kuat karena algoritma yang memanipulasi variabel dapat mempercayai bahwa variabel hanya akan mengambil salah satu dari serangkaian nilai yang terdefinisi dengan baik. Menjaga kepercayaan ini memastikan integritas dan kualitas data dan program.
Untuk banyak variabel, himpunan nilai yang dapat ditugaskan ke variabel didefinisikan pada saat program ditulis. Misalnya, variabel yang disebut "warna" mungkin diizinkan untuk mengambil nilai "merah", "hijau", atau "biru" dan tidak pernah memiliki nilai lain. Untuk variabel lain, kriteria tersebut dapat berubah pada saat dijalankan. Misalnya, variabel yang disebut "warna" hanya dapat diizinkan untuk mengambil nilai dalam kolom "nama" dari tabel "Warna" dalam database relasional, di mana "merah," hijau ", dan" biru ", adalah tiga nilai untuk "nama" di tabel "Warna", tetapi beberapa bagian lain dari program komputer mungkin dapat menambahkan ke daftar itu saat program sedang berjalan, dan variabel dapat mengambil nilai-nilai baru setelah mereka ditambahkan ke tabel Warna .
Banyak bahasa tipe-aman memberikan ilusi "keamanan-tipe" dengan menekankan pada tipe-tipe yang terdefinisi secara ketat untuk variabel-variabel dan hanya memungkinkan suatu variabel diberi nilai-nilai dari "tipe" yang sama. Ada beberapa masalah dengan pendekatan ini. Misalnya, suatu program mungkin memiliki variabel "yearOfBirth" yang merupakan tahun seseorang dilahirkan, dan tergoda untuk mengetikkannya sebagai integer pendek. Namun, ini bukan bilangan bulat pendek. Tahun ini, ini adalah angka yang kurang dari 2009 dan lebih besar dari -10000. Namun, set ini bertambah 1 setiap tahun saat program berjalan. Membuat ini "int pendek" tidak memadai. Apa yang diperlukan untuk membuat variabel-safe ini adalah fungsi validasi run-time yang memastikan bahwa jumlahnya selalu lebih besar dari -10000 dan kurang dari tahun kalender berikutnya.
Bahasa yang menggunakan pengetikan dinamis (atau pengetikan bebek, atau pengetikan manifes) seperti Perl, Python, Ruby, SQLite, dan Lua tidak memiliki gagasan tentang variabel yang diketik. Ini memaksa programmer untuk menulis rutin validasi run-time untuk setiap variabel untuk memastikan itu benar, atau menanggung konsekuensi dari pengecualian run-time yang tidak dapat dijelaskan. Dalam pengalaman saya, programmer dalam bahasa yang diketik secara statis seperti C, C ++, Java, dan C # sering terbuai dengan berpikir bahwa hanya tipe yang didefinisikan secara statis yang perlu mereka lakukan untuk mendapatkan manfaat dari keamanan tipe. Ini tidak benar untuk banyak program komputer yang berguna, dan sulit untuk memprediksi apakah itu benar untuk program komputer tertentu.
The long & the short .... Apakah Anda ingin type-safety? Jika demikian, maka tulislah fungsi run-time untuk memastikan bahwa ketika suatu variabel diberi nilai, itu sesuai dengan kriteria yang didefinisikan dengan baik. Sisi buruknya adalah hal itu membuat analisis domain sangat sulit untuk sebagian besar program komputer karena Anda harus secara eksplisit menentukan kriteria untuk setiap variabel program.