Değişkenler neden bir türe ihtiyaç duyar?


10

Bu yüzden şunu yazıyoruz:

Customer c = new Customer();

Tasarım neden yazdığımız gibi değil:

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

Derleyici, bir Müşteriye c puan verebilir ve Müşteri üyelerinin c?

Yazmak isteyebileceğimizi biliyorum:

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

Yazabilmek için:

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

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

Ama yazsaydık:

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

hala yazabiliriz:

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

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

Derleyici, c nesnesinin türü bir Name özelliğini desteklemiyorsa (yöntemdeki bağımsız değişken / parametre üzerinde hangi üyelerin kullanıldığını denetleyebildiğinden) veya çalışma zamanının şikayet edebileceği durumlarda hemen yukarıdaki koddan şikayet edebilir.

C # 'in dinamik anahtar kelimesinde bile, hala bir değişken türü (çalışma zamanında belirlenir) kullanıyoruz. Ama neden bir değişkenin bir türe ihtiyacı var? Eminim iyi bir sebep olmalı, ama düşünemiyorum!


12
Bu yüzden Python ve Ruby (ve diğerleri) gibi dinamik diller vardır. Bu sorunun cevabı yok . Bazı dillerin tür bildirimleri kullandıkları ve bazı dillerin kullanmadığı bir gerçektir.
S.Lott

2
"bu dillerdeki değişkenlerin türü yok mu?" Doğru. Python'da değişkenlerin türü yoktur. Nesnelerin bir türü vardır ve değişkenler basitçe nesnelere referanstır. Sizin soru gerçekten sadece bir gözlem. Özellikle "tüm diller değişken bildirimler gerektirmez". Cevap yok. Yani yapıcı olmadığı için kapanması muhtemeldir.
S.Lott

1
Değişkenleri herhangi bir tür bildirimi olmadan bildirmenize izin veren ancak türleri anlamak için tür çıkarımı kullanan Boo'ya bir göz atmak isteyebilirsiniz , böylece güçlü yazmanın doğruluğunu ve performans avantajlarından ödün vermemeniz gerekir.
Mason Wheeler

2
var x = 1; - 32 bit, 64 bit, 16 bit sayı mı demek istediniz? bayt? yüzer? çift? ondalık? Bu sadece ilkellerle uğraşıyor.
İş

4
varC # ' da kullanabilirsiniz ve bir değişkeni nerede bildirmek istediğiniz konusunda açık olmak her zaman iyidir.
Daniel Little

Yanıtlar:


22

Ama neden bir değişkenin bir türe ihtiyacı var?

  1. Bu, bir değişkene geçersiz, yanlış yazılan bir ifadenin atandığı hataları yakalayabilir. Bazı diller dinamik tipleme özelliğine sahiptir ; bu, istediğiniz bir esneklik türü için değişken başına bir türün doğruluk garantisini feda eder.
  2. Türler, derleyicinin daha verimli kod üretmesine izin verebilir. Dinamik yazma, tip kontrollerinin çalışma zamanında yapılması gerektiği anlamına gelir.

1
Lütfen downvote'u açıklayınız.
Fred Foo

4
Ayrıca, dinamik yazmanın bir performans maliyeti vardır, çünkü tür bilgilerinin çalışma sırasında kontrol edilmesi gerekir.
Charles Salvia

@CharlesSalvia: iyi bir nokta, bunu cevaba ekledi.
Fred Foo

2
@sturdytree: "bir türü yoksa, o zaman yanlış yazılamaz" - dil kurallarına göre, bu doğrudur. Ancak değişkene anlamsal bir bakış açısından yanlış tür atanmış olabilir , örneğin bir kurucu adını yanlış yazdınız ve program hala çalışıyor, ancak istediğinizi yapmıyor.
Fred Foo

5
@sturdytree Yazım denetimli gerçekten daktilo değişkenleri olmayan bir dil olmadığı doğru olsa da, yazım çıkarımına sahip diller vardır . Yani dil, değişkeni kullanımınıza bakar ve türü kullanımınızdan çıkarır. Bir çakışma varsa (örneğin, a = new Bar()bir yöntemi sınıftan gerçekleştirir ve daha sonra çağırırsanız Baz), derleyici bir hata oluşturur. Haskell ve OCaml gibi diller tür çıkarımına öncülük etti, ancak varanahtar kelime ile C # 'da mevcut .
Şubat'ta

9

Mükemmel geçerli bir noktanız var, değişken türünü takip etmeyen diller var ve buna "dinamik olarak yazılmış" deniyor. Kategori, JavaScript, Perl, Lisp ve Python gibi dilleri içerir.

Statik olarak yazılan bir dilden elde ettiğimiz avantaj, bazı derleme zamanı hata denetimidir.

Örneğin, aşağıdaki yönteme sahip olduğunuzu varsayalım:

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

Kodunuzda bir müşteriniz bobve bir çalışanınız varsa james, yanlışlıkla aramak addCustomerContact(james, bob), geçersizdir. Ancak derleyici değişkenlerin türlerini bilmiyorsa, geçersiz bir arama yaptığınız konusunda sizi uyaramaz, bunun yerine çalışma zamanında bir hata oluşur ... ve dinamik olarak yazılan diller iletilen parametrelerin türü, bu sorun kodunuz jamesnesnenin yalnızca müşteri özelliklerini veya nesnenin yalnızca çalışan özelliklerini kullanmaya çalıştığında oluşur bob. Bu, çiftin (james, bob) müşteri kişileri listesine eklenmesinden çok sonra olabilir.

Şimdi, neden derleyici hala türünü tahmin edemediği, merak edebilirsiniz jamesve bobve hala bizi uyarmak? Bu bazen mümkün olabilir, ancak değişkenlerin gerçekten türü yoksa, aşağıdakileri yapabiliriz:

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

Değişkenlerin türü olmadığından, herhangi bir değişkene herhangi bir değer atamak son derece yasaldır. Bu aynı zamanda bir değişkenin türünü her zaman bilemeyeceğimiz anlamına gelir, çünkü farklı yürütme yollarına dayanan farklı türlerde olabilir.

Genel olarak, dinamik olarak yazılan diller, derleme adımı olmayan komut dosyası dilleri için kullanılır ve bu nedenle derleme hataları yoktur, bu da değişken türü vermek için gereken ekstra tuş vuruşlarının çok yararlı olmayacağı anlamına gelir.

Dinamik olarak yazılan diller için de bazı avantajlar vardır, çoğunlukla aynı tasarımı uygulamak için daha az kod gerekir. , nesnenin ait olduğu sınıfa değil), değişkenlere açık bir tür verilmesine gerek yoktur ... kodumuz çalıştırılmaya başlamadan önce biraz daha az hata olduğunu öğrendik.


Teşekkürler Theodore. "Ancak derleyici değişkenlerin türlerini bilmiyorsa, geçersiz bir çağrı yaptığınız konusunda sizi uyaramaz." Belirttiğiniz gibi, derleyici değişkenlerin işaret ettiği nesnelerin türlerini bilebilir.
sturdytree

Theodore: Örneğinizde james / bob, programcılar olarak değişkenlerimizi nasıl kullandığımızı bilmeliyiz (ve iyi adlandırma yardımcı olur) ve bu yüzden onunla ilgili bir sorun görmüyorum. "Her zaman bir değişkenin türünü bilemeyiz" dediğinde, değişkenin işaret ettiği nesnenin türünü her zaman bilemeyeceğimizi varsayarım, ancak derleyici bunu çözebilir ve bu yüzden hatalı üyelerin uygulanmış (yani statik kontrolümüz olabilir).
sturdytree

2
Yukarıda, nesnelerin türlerini statik olarak bilemeyeceğiniz bir örnek verdim ... yürütme yoluna bağlı olarak, tür bilgisi olmayan bir değişkende depolanan nesne türü farklı olabilir. Derleme zamanı tür bilgisinin çıkartılabileceği C # gibi bir dile sahip olabilirsiniz, ancak bildiğim kadarıyla, hem statik tip kontrolüne hem de gerçekten türsüz değişkenlere sahip bir dil yok, statik analizin hesaplama karmaşıklığı da muhtemelen harika.
Theodore Murdock

Theodore, teşekkürler, bahsettiğim şeyin statik tip kontrolüne (nesne türüne göre) ve tipsiz değişkenlere sahip bir dil olduğunu doğru bir şekilde anladınız. Hiçbiri duyduğum için üzgünüm - Python'un daktilo değişkenleri olduğu söylendi, ancak statik tip kontrolü yok gibi geliyor.
sturtree

1
1; güçlü / zayıf tipleme statik / dinamik tiplemeye diktir. C statik olarak zayıf yazılmıştır; Lisp ve Python dinamik olarak güçlü bir şekilde yazılmıştır.
Fred Foo

5

Bu yüzden profesyonel programcılar,

10 + "10"

is "1010" or 20....

Ne olduğu, statik olarak yazılan bir dille veya dinamik olarak yazılan bir çalışma zamanıyla derleme sırasında bir hata. Zaten aklı başında olanlar.


2
Yani, Perl aklı başında bir dil değil mi? :)
Fred Foo

5
@larsmans: aslında, hayır, değil. ama bu tamamen fikir.
NotMe

2
@ChrisLively: Bunun bir gerçek meselesi olduğuna sevindim. Lütfen Perl seven arkadaşlarımı ikna etmek için her zaman işyerime gel;)
Fred Foo

2
10 + "10", tamsayı türündeki nesnelerde ve dize türündeki nesnede '+' operatörü kullanıyor. Derleyici bir hata verir. Benim sorum nesneyle değil de değişken türü ile ilgili.
sturdytree

2
Bu ise geçerli C: It adlı işaretçi aritmetiği.
dan04

4

Bir değişkeniniz olduğunu varsayarsak one(1 olarak ayarlanır) ve değerlendirmeye çalışmışsınızdır one + one. Eğer tür hakkında bir fikriniz yoksa, 1 + 1 belirsiz olacaktır. 2 veya 11'in doğru cevaplar olabileceğini iddia edebilirsiniz. Bağlam verilmezse belirsiz hale gelir.

Ben VARCHARbunun yerine veritabanları türleri yanlışlıkla yerine ayarlanmış INTve işlemleri yapıldığında insanlar beklenmedik sonuçlar elde edildi SQLite gördüm .

C # 'da içerik bir tür içeriyorsa, varanahtar kelimeyi kullanabilirsiniz .

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

Derleme zamanında c ve e çıkarım türleriyle derlenecektir.


1
Python'da 1 + 1her zaman türü vardır int, ancak bunu bildirmeye gerek yoktur. Soru, değişkenlerin neden değerleri değil, bir türü olduğu ile ilgilidir .
Fred Foo

Maalesef görmek yaratılmışız variablesdeğil valuesben kullanıldıklarında 1 + 1benim örnekte. Sanırım net değildi.
Stephen Quan

Yine de, dinamik olarak yazılmış diller bununla başa çıkabilir. Python'da one=1; print(one+one)yazdırır 2. one="1"; print(one+one)yazdırır 11. SQLite örneği daha inandırıcıdır, ancak sorun zayıf yazımlardan biridir, bu yüzden C # ile gerçekten ilgili değildir.
Fred Foo

Benim önerdiğim şemada, bir = 1 tamsayı türüne işaret eden bir değişken anlamına gelir (hiçbir tip önermiyorum - nesnelerin bir türü olurdu). bir + bir o zaman belirsiz olmaz (iki tamsayı nesnesi / değer
ekliyoruz

1
Merhaba @ dan04, ORDER BYyanlışlıkla bir VARCHARalanda yapıldığını gördüm . Bkz. Stackoverflow.com/questions/9103313/… .
Stephen Quan

4

Değişkenin ilişkili bir türe sahip olması gerekmez. Bunun doğru olduğu diller Lisp, Scheme, Erlang, Prolog, Smalltalk, Perl, Python, Ruby ve diğerlerini içerir.

Bir değişkenin bir türe sahip olması da mümkündür , ancak türü programa yazmanız gerekmeyebilir . Buna genellikle tür çıkarımı denir. ML, Haskell ve onların soyundan gelenler güçlü tip çıkarımına sahiptir; diğer bazı dillerde, C ++ 'ın autobildirimleri gibi daha küçük formlarda bulunur .

Tür çıkarımına karşı ana argüman okunabilirliğe zarar vermesidir. Türler yazıldığında kodu anlamak genellikle daha kolaydır.


1

Değişkeninizin temsil ettiği türü belirlediğinizde, birkaç şey hakkında bir açıklama yaparsınız. Değişkeniniz için bellek ayırma gereksinimlerini belirliyorsunuz ve değişkeniniz için uyumluluk ve aralık kuralları tanımlıyorsunuz. Sakladığınız veriler için niyetlerinizle ilgili karışıklıklardan kaçınmak ve derleme zamanında kodunuzdaki olası sorunları tanımlamak için nispeten ucuz bir yol sağlamaktır.

Aşağıdaki değişkenleri bildirirseniz:

myVar      = 5;
myOtherVar = "C";

Bu değişkenler hakkında neler çıkarabilirsiniz? Is myVarimzalanmış veya imzasız? 8 bit mi, 64 bit mi, yoksa arada bir şey mi? Mi myOtherVar, bir String (etkili bir dizi) ya da bir Char? ANSI veya Unicode mu?

Belirli veri türlerini sağlayarak, derleyiciye uygulamanız için bellek gereksinimlerini nasıl optimize edebileceğine dair ipuçları sağlarsınız. Bazı diller bu tür şeylerle çok fazla uğraşmazlar, bu konuların çalışma zamanında ele alınmasına izin verirken, diğer diller belirli bir miktarda dinamik yazmaya izin verir çünkü kod analiz edilerek veri türleri çıkarılabilir.

Güçlü yazılan dillere sahip bir başka nokta da, her değişken kullandığınızda derleyiciye talimat vermenize gerek kalmamasıdır. Bir değişkene her eriştiğinizde kodunuzun ne kadar korkunç ve okunamaz hale geleceğini hayal edebiliyor musunuz, derleyiciye ne tür bir değer olduğunu söylemek için etkili bir şekilde yayınlamaya zorlandınız mı? !!


İyi bir nokta, derleyici sadece değere dayalı en verimli türü (örneğin küçük int) kullanabilirsiniz, ancak bazı işlemleri gerçekleştirmek için "C" char yerine bir dize nesnesi olmasını isteyebilirsiniz görebilirsiniz . Ancak bu gibi durumlarda sadece bir = (string) "C" belirtebiliriz. Bu bir dize nesnesi oluşturur ve 'a' (türlenmemiş değişken) sadece onu işaret eder. Bu dize a = "C" daha korkunç görmüyorum;
sturdytree

0

Bir bilgisayar programı, dil çalışma zamanının temsil ettiği (çoğu durumda araç takımlarıyla genişletilen) bir "makinenin" ne sırada, hangi sırada veya hangi koşullarda yapılması gerektiğini açıklayan işlem düğümlerinin bir grafiğidir. Bu grafik, belirli bir dilde yazılmış bir metin dosyası (veya bir grup metin dosyası) ile temsil edilir ve derleyici / yorumlayıcı bu dosyayı okuduğunda (serisini kaldırdığında) (kısmen veya tamamen) oluşturulur. Ayrıca, bu grafiği gerçekten oluşturabileceğiniz ve kaynak kodu hedef dilde oluşturabileceğiniz bazı ortamlar (UML veya grafik program oluşturma araçları) vardır.

Bunu neden söylüyorum? Çünkü bu sorunuzun cevabına yol açar.

Program metniniz, hem işlem adımlarını (koşullar, eylemler) hem de yapıyı (çözümde hangi bileşenleri kullandığınızı) içeren bilgisayarın asıl görevi nasıl çözmesi gerektiğine dair talimatlarınızdır. İkincisi, diğer bileşenlerin bazı örneklerini alıp oluşturduğunuz, bunları adlandırılmış kutulara (değişkenler) koyduğunuz ve bunları kullandığınız anlamına gelir: veri ve hizmetlerine erişin.

Bazı diller size yalnızca etiketin önemli olduğu tek tip kutular verir, ancak bunlara sadece herhangi bir şey koyabilirsiniz, başında "Kişi" ve sonunda "Araba" depolamak için "hedef" adlı bir değişkeni bile kullanabilirsiniz. aynı algoritma. Diğerleri "şekilli" kutular oluşturmanızı gerektirir, bu nedenle bir Kişi veya Araba için farklı kutular oluşturmanızı gerektirir - yine de "genel bir kutu" oluşturmanıza izin verirler (Java Nesnesi, C / C ++ void *, Objective C "id" ...) ve istediğiniz gibi atabilirsiniz. Yazılan diller yapınızı daha ince ayrıntılarla ifade etmenizi sağlar, değişkenleriniz için "tip sözleşmeler" yaratır (ancak bu sınırlamayı aşmanıza rağmen), türlenmemiş diller bunu destekliyor "Bu sefer o kutuya ne koyduğumu kesinlikle bileceğim" yaklaşımı varsayılan ve tek davranış olarak.

Her iki yaklaşım da uygulanabilir, derleyici istihbaratlarına, birçok programlama kitabına, uygulamalara ve çerçevelere (ve bu çerçevelerle ilgili diğer tonlarca kitap) farklı seviyelerde yazılmıştır. Yani bugün cevap, tiplerin kullanılıp kullanılmayacağına dair doğru kurulmuş, ölçülmüş ve doğrulanmış bir açıklamadan ziyade gerçek programcı ekibinin bilgisi meselesi gibi görünüyor.

Özellikle uzun vadeli büyük ekip (aka: "ciddi") projeleri için kuralları tercih ettiğimi söylemenin gereksiz olduğunu düşünüyorum. Sebep: bildiğim kadarıyla, bir SW projesi başarısızlığının / kaymasının en olası nedenleri: belirsiz gereksinimler ve zayıf tasarım (bildiğim bir çalışma ile% 80!) Ve gerçek kodlama için sadece yüzde birkaç kaldı. Tüm kurallar ve sözleşmeler, daha ileriyi düşünerek daha temiz bir tasarım uygular ve kararların daha önce ve uygun kişiler tarafından alınmasını gerektirir. Türler kurallar anlamına gelir: daha az "özgürlük" ve "serinlik" - daha fazla hazırlık, düşünme, kodlama standartları, kontrollü ekip çalışması. Bana göre bu, gerekli bir başarı faktörü ve aynı zamanda "ev, tatlı ev" gibi geliyor.

Benim 2 sentim.


-3

AFIAK dinamik yazım içeren tüm diller yorumlanmış dillerdir. Bu zaten çok verimsiz, dinamik yazmanın verimsizliğini eklemek büyük bir zaman kaybı olmayacak. Derlenmiş bir dil, aslında çalışırken isimlere bir şeyden söz etmeyecektir. (Altta yatan dile kıyasla çok yavaş olan .net yansıması veya benzeri özelliklerin ara sıra kullanımını engellemek.) Tüm bu adları aramak yavaş, yavaş, yavaş olacaktır.


3
Yanlış biliyorsun. Dinamik olarak yazılan diller için birçok derleyici vardır ve bazıları oldukça hızlıdır. Örnekler arasında Common Lisp, Scheme ve Erlang sayılabilir.
Ryan Culpepper

3
"Yorumlanmış dil" diye bir şey yoktur. Dil, soyut bir matematiksel kurallar kümesidir. Bir dil ne derlenir ne de yorumlanır. Bir dil sadece. Derleme ve yorumlama dilin değil uygulamanın özelliğidir. Her dil bir tercüman ile uygulanabilir ve her dil bir derleyici ile uygulanabilir. Ve hemen hemen her dil hem yorumlanmış hem de derlenmiş uygulamalara sahiptir, örneğin C için tercümanlar ve ECMAScript, Ruby ve Python için derleyiciler vardır.
Jörg W Mittag

-4

Dinamik olarak yazılan diller genellikle "nesne yönelimli" olarak adlandırılır. Onlar değil. Kapsülleme yönelimli olabilirler, ancak asla nesne yönelimli olmayabilirler. Nesne yönelimi tamamen türlerle ilgilidir.

"Çocuk kardeşinin bisikletini markete sürüyor ve bakkaldan bir somun ekmek alıyor". Nesne yönelimini kullanarak, bu gerçek dünya senaryosunu tanımlamak için derhal bir dizi sınıf (tip) yazılabilir.

Dinamik olarak yazılan bir dilde, senaryo yalnızca bu şekilde temsil edilebilir:

"Nesne, nesnesinin nesnesini nesneye sürüyor ve nesneden bir nesne alıyor".

Nesne yöneliminin gücü, dünyayı doğal terimlerle modelleme yeteneğine sahiptir, böylece yazılım geliştiricisi, beynin her iki tarafını da yazılım yazmak için kullanabilir ve sorunları bir insan olarak, daha az bir bilgisayar programcısı olarak çözebilir. Bu güç, dinamik olarak yazılan dillerde yoktur.

Statik yazım, daha iyi kodlama verimliliği, yeniden kullanılabilirlik ve sürdürülebilirlik sağlar, çünkü entegre geliştirme ortamları değişken türlerini bilir. Değişken türlerini bilerek, IDE otomatik tamamlama sağlayabilir, böylece programcı üye özelliğinin "backlightControl" veya "backLightControl" veya "bkLightCtrl" yazıldığını hatırlamak için sınıf tanımına geri başvurmak zorunda kalmaz.

Statik yazım otomatik yeniden düzenlemeye izin verir, çünkü IDE, bir değişkenin yeniden düzenlenen nesnenin bir örneğini bulunduğu her yeri bilir.

Statik yazım, daha fazla yeniden kullanılabilirlik ve bakım kolaylığı sağlar. Tek kullanımlık kod için dinamik yazma daha iyidir. Yeni bir geliştiricinin caddeden çıktığını ve mevcut bir kod parçasına baktığını varsayalım. Kod statik olarak yazılırsa, geliştirici, iki fare tıklamasıyla, ilgili değişkenlerin her birinin sınıf tanımını inceleyebilir, sınıfın ne için olduğunu bilir, başka hangi yöntemlerin ve özelliklerin kullanılabilir olduğunu bilir. Kod dinamik olarak yazılırsa, geliştiricinin neler olduğunu anlamak için genel aramayı kullanması gerekir.


2
Korkarım tartışmanızın ilk kısmında size katılmama gerek var. Dinamik olarak yazılan diller genellikle "nesne yönelimli" dir, ancak "sınıf yönelimli" değildir. Bu önemli bir ayrım. Örneğin, aslında bir yanılsamada yaşıyorsunuz. Bir Boysınıfınız olabilir , ama gerçek bir dünyanın “oğlan” ının yaptığı her şeyi yapabileceğinden şüpheliyim. Bununla birlikte, dinamik örneğinizde (Nesne sürüyor ...), bu "çocuk" nesnesi hakkında tek önemli şeyi biliyoruz - atabiliyor . Dinamik tip dillerin temel felsefesi budur. + Ve s ve -ve s'dir. Hangisini seviyorsun?
Chip
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.