it-swarm-tr.com

Java, Javascript ve C # gibi bellek tarafından yönetilen diller neden `new` anahtar kelimesini korudu?

Java, Javascript ve C # gibi dillerde new anahtar kelimesi yeni bir sınıf örneği oluşturur.

Bu sözdizimi C++ 'dan miras alınmış gibi görünüyor, burada new özellikle bir sınıfın yeni bir örneğini yığın üzerinde tahsis etmek ve yeni örneğe bir işaretçi döndürmek için kullanılır. C++ 'da, bu bir nesne oluşturmak için tek yol değildir. Ayrıca, new kullanmadan yığın üzerinde bir nesne de oluşturabilirsiniz - ve aslında, bu nesne oluşturma yöntemi C++ 'da çok daha yaygındır.

Dolayısıyla, bir C++ arka planından gelen Java, Javascript ve C # gibi dillerde new anahtar kelimesi benim için doğal ve açık görünüyordu. Sonra new anahtar kelimesine sahip olmayan Python öğrenmeye başladım. Python'da, bir örnek basitçe kurucu çağrılarak oluşturulur, örneğin:

f = Foo()

İlk başta, bu bana biraz kapalı görünüyordu, bana kadar Python new 'a sahip olmanın bir nedeni olmadığı için, her şey bir nesne olduğundan, gerek yok çeşitli kurucu sözdizimleri arasında ayrım yapmak.

Ama sonra düşündüm - Java'daki new 'nin gerçekten anlamı nedir? Neden Object o = new Object(); diyelim? Neden sadece Object o = Object(); değil? C++ 'da kesinlikle new' a ihtiyaç vardır, çünkü yığın üzerinde ayırma ve yığın üzerinde ayırma arasında ayrım yapmamız gerekir, ancak Java tüm nesneler yığın üzerinde oluşturulur, Peki neden new anahtar kelime var? Aynı soru Javascript için sorulan olabilir.Çok daha az aşina olduğum C #, ben new ayırma açısından bir amacı olabilir düşünüyorum nesne türleri ve değer türleri arasında, ama emin değilim.

Ne olursa olsun, C++ 'dan sonra gelen birçok dilin new anahtar kelimesini gerçekten ihtiyaç duymadan basitçe "devralması" gibi görünüyor. Neredeyse bir anahtar kelime gibi. Herhangi bir nedenle buna ihtiyacımız yok gibi görünüyor, ama yine de orada.

Soru: Bu konuda doğru muyum? Veya C++ - Java, Javascript ve C # gibi ilham alan bellek tarafından yönetilen dillerde Python'da olmasa da new olmasının zorlayıcı bir nedeni var mı?

141
Channel72

Gözlemleriniz doğru. C++ karmaşık bir canavardır ve new anahtar kelimesi, delete ve sonrasında otomatik olarak geri alınacak bir şeyi ayırt etmek için kullanıldı. Java ve C # 'da, çöp toplayıcı sizin için ilgileneceği için delete anahtar kelimesini bıraktılar.

O zaman sorun new anahtar kelimesini neden sakladı? Dili yazan insanlarla konuşmadan cevaplamak biraz zor. En iyi tahminlerim aşağıda listelenmiştir:

  • anlamsal olarak doğruydu. C++ ile tanıştıysanız, new anahtar kelimesinin yığın üzerinde bir nesne oluşturduğunu biliyordunuz. Peki, beklenen davranışı neden değiştirelim?
  • Bir yöntemi çağırmak yerine nesneyi başlattığınıza dikkat çekiyor. Microsoft kod stili önerileriyle, yöntem adları büyük harflerle başlar, böylece karışıklık olabilir.

Ruby, Python ve Java/C # arasında new kullanımında bir yerdedir. Temel olarak şöyle bir nesne başlatırsınız:

f = Foo.new()

Bu bir anahtar kelime değil, sınıf için statik bir yöntem. Bunun anlamı, tek birton istiyorsanız, her seferinde aynı örneği döndürmek için varsayılan new() uygulamasını geçersiz kılabilirsiniz. Mutlaka tavsiye edilmez, ancak mümkündür.

97
Berin Loritsch

Kısacası haklısın. Yeni anahtar kelime Java ve C # gibi dillerde gereksizdir. 1990'larda C++ Standard Comitee üyesi olan ve daha sonra Java ile ilgili kitaplar yayınlayan Bruce Eckel'in bazı bilgileri: http://www.artima.com/weblogs/viewpost.jsp?thread=260578

yığın nesnelerini yığın nesnelerinden ayırmanın bir yolu olması gerekiyordu. Bu sorunu çözmek için yeni anahtar kelime Smalltalk'tan alınmıştır. Bir yığın nesnesi oluşturmak için Cat x'te olduğu gibi basitçe bildirirsiniz; veya argümanlarla Cat x ("eldivenler"); Bir yığın nesnesi oluşturmak için yeni Cat'te olduğu gibi new'i kullanırsınız; veya yeni Kedi ("eldiven"); Kısıtlamalar göz önüne alındığında, bu zarif ve tutarlı bir çözümdür.

C++ 'ın her şeyin kötü bir şekilde yapıldığını ve aşırı derecede karmaşık olduğuna karar verdikten sonra Java'ya girin. Buradaki ironi, Java, yığın tahsisini atma kararı verebildi ve (başka bir yerde ele aldığım ilkellerin tartışmasını göz ardı ederek). Ve tüm nesneler öbek üzerinde tahsis edildiğinden, yığın ve yığın dağılımı arasında ayrım yapmaya gerek yoktur. Kolayca Cat x = Cat () veya Cat x = Cat ("eldiven") diyebilirlerdi. Ya da daha iyisi, tekrarı ortadan kaldırmak için birleşik tür çıkarımı (ancak - ve kapaklar gibi diğer özellikler - "çok uzun" olurdu, bu yüzden Java'nin vasat sürümü ile sıkıştık; tartışıldı ama gerçekleşmeyeceği ihtimalleri ortaya koyacağım ve Java'ya yeni özellikler eklemede problemler göz önüne alındığında olmamalı).

87
Nemanja Trifunovic

Düşünebilmem için iki neden var:

  • new bir nesne ile ilkel arasında ayrım yapar
  • new sözdizimi biraz daha okunabilir (IMO)

Birincisi önemsiz. İkisini her iki şekilde birbirinden ayırmanın daha zor olduğunu düşünmüyorum. İkincisi, OP'nin noktasına bir örnektir, yani new bir tür gereksizdir.

Yine de ad alanı çakışmaları olabilir; düşünmek:

public class Foo {
   Foo() {
      // Constructor
   }
}

public class Bar {
   public static void main(String[] args) {
      Foo f = Foo();
   }

   public Foo Foo() {
      return Foo();
   }
}

Hayal gücünüzü çok fazla germeden, kolayca sonsuz bir özyinelemeli çağrı ile sonuçlanabilirsiniz. Derleyicinin "nesne ile aynı işlev adı" hatasını zorlaması gerekir. Bu gerçekten acıtmaz, ancak new 'ı kullanmak çok daha kolaydır, bu da Go to the object of the same name as this method and use the method that matches this signature. Java ayrıştırmak için çok basit bir dildir ve bunun bu alanda yardımcı olduğundan şüpheleniyorum.

15
Michael K

Birincisi, Java hala C++ ikilemine sahiptir: değil oldukça her şey bir nesnedir. Java, dinamik olarak ayrılması gerekmeyen yerleşik türlere (ör. char ve int) sahiptir.

Bu, Java olsa da) new'nin gerçekten gerekli olduğu anlamına gelmez - dinamik olarak tahsis edilmesi gerekmeyen türler kümesi sabit ve bilinir. bir nesne, derleyici char basit bir değer veya dinamik olarak tahsis edilmesi gereken bir nesne olup olmadığını bilebilir (ve aslında bilir).

Java tasarımının kalitesi (veya duruma göre eksikliği) hakkında bunun ne anlama geldiğini seçmekten (yine) kaçınacağım.

10
Jerry Coffin

JavaScript'te, yapıcı normal bir işlev gibi göründüğü için buna ihtiyacınız vardır, bu nedenle JS, yeni anahtar kelime için değilse yeni bir nesne oluşturmak istediğinizi nasıl bilebilir?

new operatörü ile bir JavaScript işlevi çağırmak, new operatörü olmadan bir işlevi çağırmaktan farklı bir davranışla sonuçlanır.

Örneğin:

Date()       //Returns a string

new Date()   //Returns a Date object
function foo() {};

foo()        //Returns `undefined`

new foo()    //Returns an empty object
10
user281377

Ben çok cevap istiyorum ve sadece bunu eklemek istiyorum:
Kod okumayı kolaylaştırır
Bu durumun sık sık yaşanacağından değil, bir isim ile aynı adı paylaşan bir fiil adına bir yöntem istediğinizi düşünün. C # ve diğer diller doğal olarak object kelimesine sahiptir. Ancak o olmasaydı Foo = object() nesne yöntemi çağrısının sonucu olurdu ya da yeni bir nesne başlatır mıydı. İnşallah new anahtar kelimesi olmayan dilin bu duruma karşı korumaları vardır, ancak bir yapıcı çağrılmadan önce new anahtar sözcüğü gerekliliği ile aynı ada sahip bir yöntemin varlığına izin verirsiniz. bir obje.

4
Kavet Kerek

İlginçtir, VB yok buna ihtiyaç var - arasındaki ayrım

Dim f As Foo

bir değişkeni atamadan bildirir, C # içindeki Foo f; eşdeğerini ve

Dim f As New Foo()

değişkeni bildiren ve C # 'daki var f = new Foo(); eşdeğeri olan sınıfın yeni bir örneğini atayan, önemli bir ayrımdır. Pre..NET VB'de, Dim f As Foo Veya Dim f As New Foo Kullanabilirsiniz - çünkü kuruculara aşırı yükleme yapılmamıştır.

4
Richard Gadsden

Birçok programlama dilinde çok fazla şey var. Bazen tasarımla oradadır (C++, C ile mümkün olduğunca uyumlu olacak şekilde tasarlanmıştır), bazen sadece oradadır. Daha açıklayıcı bir örnek için, kırık C switch ifadesinin ne kadar yayıldığını düşünün.

Javascript ve C # söyleyecek kadar iyi bilmiyorum, ama Java dışında C++ vardı) new için bir neden göremiyorum.

3
David Thornley

C # 'da, başka türlü bir üye tarafından gizlenebilecek bağlamlarda görünen türlere izin verir. Bu, türüyle aynı ada sahip bir özelliğe sahip olmanızı sağlar. Aşağıdakileri göz önünde bulundur,

class Address { 
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

class Person {
    public string Name { get; set; }
    public Address Address { get; set; }

    public void ChangeStreet(string newStreet) {
        Address = new Address { 
            Street = newStreet, 
            City = Address.City,
            State = Address.State,
            Zip = Address.Zip
        };
    }
}

new kullanımının Address 'ın Address üyesi değil Address türü olduğunu açıkça belirtmesine izin verdiğini unutmayın. Bu, bir üyenin türüyle aynı ada sahip olmasını sağlar. Bu olmadan, ad çakışmasını önlemek için CAddress gibi türün adının önüne ön ek eklemeniz gerekir. Anders hiçbir zaman Macarca gösterimi ya da benzer bir şeyi sevmediği ve C # 'ın onsuz kullanılabilir olmasını istediği için bu çok kasıtlıydı. Ayrıca tanıdık olduğu bir çift bonus oldu.

3
chuckj

Java tasarımcıların bunu göz önünde bulundurduğundan emin değilim ama nesneleri özyinelemeli kayıtlar olarak düşündüğünüzde, o zaman Foo(123) bir nesneyi değil, düzeltme noktası oluşturulmakta olan nesne olan bir işlevi döndürür (yani, oluşturulan nesnenin bağımsız değişkeni olarak nesneyi döndürecek olan işlev). Ve new 'nin amacı "bağlamaktır" Başka bir deyişle new, "olması gereken nesneyi" self öğesinin farkında kılacaktır.

Bu tür bir yaklaşım, mirasın resmileştirilmesine yardımcı olabilir: bir nesne işlevini başka bir nesne işleviyle genişletebilir ve son olarak self kullanarak onlara ortak new sağlayabilirsiniz:

cp = new (Colored("Blue") & Line(0, 0, 100, 100))

Buraya & iki nesne fonksiyonunu birleştirir.

Bu durumda new şu şekilde tanımlanabilir:

def new(objectFunction) {
    actualObject = objectFunction(actualObject)
    return actualObject
}
0
Aivar

İlginç bir şekilde, mükemmel yönlendirmenin ortaya çıkmasıyla, C++ 'da yerleşimsiz new gerekmez. Yani, tartışmalı olarak, artık bu dillerden herhangi birinde gerekli değildir.

0
DeadMG