Değişmez nesneler iyiyse, insanlar neden değişken nesneler oluşturmaya devam ediyor? [kapalı]


250

Değişmez nesneler¹ iyi, basit ve eşzamanlı programlamada faydalar sağlıyorsa, programcılar neden değişken nesneler oluşturmaya devam ediyor?

Java programlama konusunda dört yıllık bir deneyime sahibim ve gördüğüm gibi, insanların bir sınıf oluşturduktan sonra ilk yaptığı şey IDE'de alıcılar ve ayarlayıcılar üretmektir (bu nedenle değiştirilebilir hale getirmektir). Bir farkındalık eksikliği var mı yoksa çoğu senaryoda değişken nesneler kullanmaktan kurtulabilir miyiz?


Mm Değişmez nesne , oluşturulduktan sonra durumu değiştirilemeyen bir nesnedir.
² Değişken nesne , oluşturulduktan sonra değiştirilebilen bir nesnedir.


42
Bence, meşru sebeplerin dışında (aşağıda Péter tarafından bahsedildiği gibi), "tembel geliştirici", "aptal" geliştirici "den daha yaygın bir nedendir ve" aptal geliştirici "den önce" bilgisiz geliştirici "de var
Joachim Sauer

201
Her Evanjelist programcı / blogcu için hemen kendilerini yeniden icat eden ve en yeni teknikleri kullanan 1000 hevesli blog okuyucusu var. Bunların her biri için 10,000 programcı var, burnu öğütme taşına bir gün iş yaptırıyor ve kapıdan ürün alıyor. Bu adamlar yıllardır kendileri için çalışmış olan denenmiş ve güvenilir teknikleri kullanıyorlar. Yeni teknikler yaygın olarak kabul edilene kadar beklerler ve onları almadan önce gerçek faydalar gösterirler. Onlara aptal deme, ve onlar tembel olmaktan başka, yerine "meşgul" deyin.
İkili Korku

22
@BinaryWorrier: değişmez nesneler pek "yeni bir şey" değildir. Etki alanı nesneleri için yoğun bir şekilde kullanılmamış olabilirler, ancak Java ve C # onları en baştan kullanıyorlardı. Ayrıca: "tembel" her zaman kötü bir kelime değildir, bazı "tembel" türleri bir geliştirici için mutlak bir avantajdır.
Joachim Sauer

11
@Joachim: "Tembel" in aşağılık anlamında kullanıldığının oldukça açık olduğunu düşünüyorum :) Ayrıca, Immutable Objects (günümüzde Lambda Calculus ve OOP gibi - evet, o kadar yaşlıyım) yeni olmak zorunda değil aniden ayın tadı olur . Onların kötü bir şey olduklarını (değiller) ya da kendi yerlerine sahip olmadıklarını (belli ki yapıyorlar) tartışmıyorum, sadece insanlar için kolay olun çünkü en son İyi Söz'ü duymamışlardı ve hararetli bir şekilde kendisi olarak değiştirildi ("tembel" yorum için seni suçlamıyor, onu hafifletmeye çalıştığını biliyorum).
İkili Korku

116
-1, değişmez nesneler 'iyi' değildir. Belirli durumlar için daha az ya da çok uygun. Size bir teknik ya da bir başkasını söyleyen herkes, tüm durumlar için nesnel olarak "iyi" veya "kötü" dür.
GrandmasterB

Yanıtlar:


326

Değişebilir ve değişmez nesnelerin her ikisinin de kendi kullanımları, artıları ve eksileri vardır.

Gerçekleştirilemeyen nesneler birçok durumda hayatı gerçekten kolaylaştırır. Özellikle nesnelerin kimliğinin olmadığı, kolaylıkla değiştirilebilecekleri değer türleri için geçerlidir. Ayrıca eşzamanlı programlamayı daha güvenli ve daha temiz hale getirebilirler (eşzamanlılık hatalarını bulmak en önemlisi zorlukla nihayetinde dişler arasında paylaşılan değişken durumdan kaynaklanır). Bununla birlikte, büyük ve / veya karmaşık nesneler için, her bir değişiklik için nesnenin yeni bir kopyasını oluşturmak çok maliyetli ve / veya sıkıcı olabilir. Farklı bir kimliğe sahip nesneler için, mevcut nesneleri değiştirmek, değiştirilmiş yeni bir kopyasını oluşturmaktan çok daha basit ve sezgiseldir.

Bir oyun karakteri düşünün. Oyunlarda hız önceliklidir, bu nedenle oyun karakterlerinizi değişken nesnelerle temsil etmek, oyunun her küçük değişiklik için oyun karakterinin yeni bir kopyasının üretildiği alternatif bir uygulamadan çok daha hızlı çalışmasını sağlar.

Dahası, gerçek dünya hakkındaki algımız kaçınılmaz olarak değişken nesnelere dayanmaktadır. Arabanızı benzin istasyonunda yakıtla doldurduğunuzda, onu tümüyle aynı nesne olarak algılarsınız (yani , durumu değişirken kimliği korunur ) - boş bir depoya sahip eski araba arka arkaya yenisiyle değiştirilmiş gibi değil araba örnekleri tanklarını yavaş yavaş gittikçe daha dolu hale getiriyor. Dolayısıyla, ne zaman bir gerçek dünya alanını bir programda modelleniyorsak, gerçek dünya varlıklarını temsil etmek için etkilenebilir modeli kullanarak etki alanı modelini uygulamak genellikle daha kolay ve kolaydır.

Bütün bu meşru sebeplerin yanı sıra, ne yazık ki, insanların değişken nesneler yaratmaya devam etmelerinin en muhtemel nedeni, zihinsel atalet, yani değişime dirençtir. Bugünün çoğu geliştiricisinin değişmezlikten (ve içerdiği paradigmadan, işlevsel programlamadan) etki alanı içinde "moda" haline gelmeden önce iyi eğitildiklerini ve ticaretimizin yeni araçları ve yöntemleri hakkındaki bilgilerini güncel tutmadıklarını unutmayın - Aslında, birçoğumuz insan olumlu yeni fikirlere ve süreçlere direnir . "Ben daha böyle programlama edilmiş nn yıl ve son aptal heveslere umurumda değil!"


27
Doğru. Özellikle GUI programlamada değişken nesneler çok kullanışlıdır.
Florian Salihovic

23
Bu sadece bir direnç değil, pek çok dev en son ve en iyisini denemek isterdi, ama ortalama bir ortamda bu yeni uygulamaları uygulayabilecekleri ortamlarda yeni projeler ne sıklıkta ortaya çıkıyor? Evrenne değil, sadece değişmez durumu denemek için bir hobi projesi yazabilir veya yazamaz.
Steven Evers

29
Bunun için iki küçük uyarı: (1) Hareketli oyun karakterini al. PointÖrneğin .NET sınıf değişmez ama değişikliklerin sonucu kolay ve dolayısıyla ekonomik olarak yeni noktaları oluşturarak olduğunu. Değişmez bir karakterin canlandırılması, “hareketli parçaların” ayrıştırılmasıyla çok ucuza yapılabilir (ama evet, bir kısmı daha sonra değiştirilebilir). (2) “büyük ve / veya karmaşık nesneler” çok değişkendir. Dizeler genellikle büyüktür ve genellikle değişmezlikten yararlanır. Bir zamanlar kodun daha basit ve daha verimli olması için değişmez olacak şekilde karmaşık bir grafik sınıfını yeniden yazdım. Bu gibi durumlarda, değişken bir kurucuya sahip olmak anahtardır.
Konrad Rudolph

4
@KonradRudolph, iyi noktalar, teşekkürler. Karmaşık nesnelerde değişmezliği kullanmaktan kaçınmak istemedim, ama böyle bir sınıfı doğru ve verimli bir şekilde uygulamak önemsiz bir iş olmaktan uzaktı ve gereken ekstra çaba her zaman haklı gösterilmeyebilir.
Péter Török

6
Devlet ve kimlik hakkında iyi bir noktaya değindin. Bu yüzden Rich Hickey (Clojure'nin yazarı) Clojure'de ikisini birbirinden ayırdı. Biri, 1/2 tank gaz ile sahip olduğunuz aracın 1/4 tank gaz ile aynı araba olmadığını iddia edebilir. Aynı kimlikleri var, ama aynı değiller, gerçekliğimizin zamanının her "kenesi" dünyamızdaki her nesnenin bir klonunu yaratıyor, beyinlerimiz daha sonra bunları ortak bir kimlikle birleştiriyor. Clojure zamanı temsil etmek için refe, atom, ajan vb. Ve gerçek zamanlı haritalar, vektörler ve listeler.
Timothy Baldridge,

130

Sanırım hepiniz en bariz cevabı kaçırdınız. Çoğu geliştirici değişken nesneler oluşturur çünkü değişkenlik zorunlu dillerde varsayılandır. Birçoğumuz zamanımızla ilgili olarak kodları varsayılan ayarlardan uzağa sürekli olarak değiştirmekten daha iyi şeyler yapıyoruz - daha doğru ya da değil. Ve değişmezlik başka bir yaklaşımdan daha derde deva değil. Bazı şeyleri kolaylaştırır ancak bazı cevapların daha önce işaret ettiği gibi diğerlerini daha da zorlaştırır.


9
Bildiğim çoğu modern IDE'de, pratikte sadece alıcılar ve alıcılar üretmek için aynı miktarda çaba harcıyor. Her ne kadar ekleme final, constvb. Biraz fazladan çaba gerektirse de doğru olsa da ... bir kod şablonu ayarlamadıysanız :-)
Péter Török

10
@ PéterTörök sadece ek bir çaba değil, kodlayıcı stilinizi deneyimlerinize çok yabancı buldukları için kodlayıcı stilinizin sizi etkili bir şekilde asmak isteyeceği gerçeğidir. Bu da böyle bir şeyi cesaretlendirir.
Onorio Catenacci

5
Daha fazla iletişim ve eğitim ile bunun üstesinden gelinebilir, örneğin, mevcut bir kod tabanına girmeden önce yeni bir kodlama stili hakkında birinin takım arkadaşlarına konuşması veya sunum yapması önerilir. İyi bir projenin, her (geçmiş ve şimdiki) proje üyesi tarafından tercih edilen kodlama stillerinin bir karışımı olmayan ortak bir kodlama stiline sahip olduğu doğrudur. Bu yüzden kodlama deyimlerini tanıtmak veya değiştirmek bir takım kararı olmalıdır.
Péter Török

3
@ PéterTörök Zorunlu bir dilde değişken nesneler varsayılan davranışlardır. Yalnızca değişmez nesneler istiyorsanız, işlevsel bir dile geçmek en iyisidir.
emory

3
@ PéterTörök Değişmezliği bir programa dahil etmenin tüm belirleyicileri bırakmaktan başka bir şey içermediğini varsaymak biraz saf. Programın durumunun aşamalı olarak değişmesi için hala bir yönteme ihtiyacınız var ve bunun için, belirleyicilerin sadece bırakma çabalarının yaklaşık 1 milyar katı harcayan inşaatçılara, buzlu şekerlere karşı değişkenliğe veya değişken proxy'lere ihtiyacınız var.
Asad Saeeduddin

49
  1. Değişebilirlik için bir yer var. Etki alanına dayalı tasarım ilkeleri, neyin değişebilir olması ve neyin değişmemesi gerektiği konusunda sağlam bir anlayış sağlar. Eğer bunu düşünürseniz, bir nesneye yapılan her devlet değişikliğinin, onun imhasını ve onun yeniden birleştirilmesini ve onu referans alan her bir nesneye ihtiyaç duyduğu bir sistemi kavramanın pratik olmadığını fark edersiniz. Karmaşık sistemlerde bu, tüm sistemin nesne grafiğini tamamen silmeye ve yeniden oluşturmaya kolayca yol açabilir

  2. Çoğu geliştirici, performans gereksinimlerinin eşzamanlılık (ya da bilgi sahibi tarafından evrensel olarak iyi uygulama olarak kabul edilen birçok uygulama) üzerinde yoğunlaşmaya ihtiyaç duydukları kadar önemli olduğu yerlerde hiçbir şey yapmaz.

  3. İki yönlü ilişkilerde olduğu gibi, değişmez nesnelerle yapamayacağınız bazı şeyler var. Bir nesnede bir ilişkilendirme değeri belirledikten sonra, kimlik değişir. Böylece, yeni değeri diğer nesneye ayarladınız ve aynı zamanda değişiyor. Sorun, ilk nesnenin referansı artık geçerli değil çünkü nesneyi referansla temsil etmek üzere yeni bir örnek yaratıldı. Buna devam etmek sadece sonsuz gerileme ile sonuçlanacaktır. Sorunuzu okuduktan sonra küçük bir vaka incelemesi yaptım, işte nasıl görünüyor. Değişmezliği korurken bu tür işlevlere izin veren alternatif bir yaklaşımınız var mı?

        public class ImmutablePerson { 
    
         public ImmutablePerson(string name, ImmutableEventList eventsToAttend)
         {
              this.name = name;
              this.eventsToAttend = eventsToAttend;
         }
         private string name;
         private ImmutableEventList eventsToAttend;
    
         public string Name { get { return this.name; } }
    
         public ImmutablePerson RSVP(ImmutableEvent immutableEvent){
             // the person is RSVPing an event, thus mutating the state 
             // of the eventsToAttend.  so we need a new person with a reference
             // to the new Event
             ImmutableEvent newEvent = immutableEvent.OnRSVPReceived(this);
             ImmutableEventList newEvents = this.eventsToAttend.Add(newEvent));
             var newSelf = new ImmutablePerson(name, newEvents);
             return newSelf;
         }
        }
    
        public class ImmutableEvent { 
         public ImmutableEvent(DateTime when, ImmutablePersonList peopleAttending, ImmutablePersonList peopleNotAttending){
             this.when = when;     
             this.peopleAttending = peopleAttending;
             this.peopleNotAttending = peopleNotAttending;
         }
         private DateTime when; 
         private ImmutablePersonList peopleAttending;
         private ImmutablePersonList peopleNotAttending;
         public ImmutableEvent OnReschedule(DateTime when){
               return new ImmutableEvent(when,peopleAttending,peopleNotAttending);
         }
         //  notice that this will be an infinite loop, because everytime one counterpart
         //  of the bidirectional relationship is added, its containing object changes
         //  meaning it must re construct a different version of itself to 
         //  represent the mutated state, the other one must update its
         //  reference thereby obsoleting the reference of the first object to it, and 
         //  necessitating recursion
         public ImmutableEvent OnRSVPReceived(ImmutablePerson immutablePerson){
               if(this.peopleAttending.Contains(immutablePerson)) return this;
               ImmutablePersonList attending = this.peopleAttending.Add(immutablePerson);
               ImmutablePersonList notAttending = this.peopleNotAttending.Contains( immutablePerson ) 
                                    ? peopleNotAttending.Remove(immutablePerson)
                                    : peopleNotAttending;
               return new ImmutableEvent(when, attending, notAttending);
         }
        }
        public class ImmutablePersonList
        {
          private ImmutablePerson[] immutablePeople;
          public ImmutablePersonList(ImmutablePerson[] immutablePeople){
              this.immutablePeople = immutablePeople;
          }
          public ImmutablePersonList Add(ImmutablePerson newPerson){
              if(this.Contains(newPerson)) return this;
              ImmutablePerson[] newPeople = new ImmutablePerson[immutablePeople.Length];
              for(var i=0;i<immutablePeople.Length;i++)
                  newPeople[i] = this.immutablePeople[i];
              newPeople[immutablePeople.Length] = newPerson;
          }
          public ImmutablePersonList Remove(ImmutablePerson newPerson){
              if(immutablePeople.IndexOf(newPerson) != -1)
              ImmutablePerson[] newPeople = new ImmutablePerson[immutablePeople.Length-2];
              bool hasPassedRemoval = false;
              for(var i=0;i<immutablePeople.Length;i++)
              {
                 hasPassedRemoval = hasPassedRemoval || immutablePeople[i] == newPerson;
                 newPeople[i] = this.immutablePeople[hasPassedRemoval ? i + 1 : i];
              }
              return new ImmutablePersonList(newPeople);
          }
          public bool Contains(ImmutablePerson immutablePerson){ 
             return this.immutablePeople.IndexOf(immutablePerson) != -1;
          } 
        }
        public class ImmutableEventList
        {
          private ImmutableEvent[] immutableEvents;
          public ImmutableEventList(ImmutableEvent[] immutableEvents){
              this.immutableEvents = immutableEvents;
          }
          public ImmutableEventList Add(ImmutableEvent newEvent){
              if(this.Contains(newEvent)) return this;
              ImmutableEvent[] newEvents= new ImmutableEvent[immutableEvents.Length];
              for(var i=0;i<immutableEvents.Length;i++)
                  newEvents[i] = this.immutableEvents[i];
              newEvents[immutableEvents.Length] = newEvent;
          }
          public ImmutableEventList Remove(ImmutableEvent newEvent){
              if(immutableEvents.IndexOf(newEvent) != -1)
              ImmutableEvent[] newEvents = new ImmutableEvent[immutableEvents.Length-2];
              bool hasPassedRemoval = false;
              for(var i=0;i<immutablePeople.Length;i++)
              {
                 hasPassedRemoval = hasPassedRemoval || immutableEvents[i] == newEvent;
                 newEvents[i] = this.immutableEvents[hasPassedRemoval ? i + 1 : i];
              }
              return new ImmutableEventList(newPeople);
          }
          public bool Contains(ImmutableEvent immutableEvent){ 
             return this.immutableEvent.IndexOf(immutableEvent) != -1;
          } 
        }
    

2
@AndresF., Sadece değişmez nesneleri kullanarak çift yönlü ilişkilerle karmaşık grafiklerin nasıl korunacağına dair farklı bir yaklaşımınız varsa, o zaman duymayı çok isterim. (Bir koleksiyonun / dizinin bir nesne olduğu konusunda hemfikir olduğumuzu farzediyorum)
smartcaveman

2
@AndresF., (1) İlk açıklamam evrensel değildi, bu yüzden yanlış değildi. Aslında uygulama geliştirmede çok yaygın olan bazı durumlarda zorunlu olarak nasıl doğru olduğunu açıklamak için bir kod örneği verdim. (2) İki yönlü ilişkiler, genel olarak değişkenlik gerektirir. Java'nın suçlu olduğuna inanmıyorum. Söylediğim gibi, önereceğiniz herhangi bir yapıcı alternatifi değerlendirmekten memnuniyet duyarım , ama bu noktada yorumlarınız "Yanlış söyledim çünkü yanılıyorsunuz" gibi ses çıkarıyorsunuz.
smartcaveman

14
@smartcaveman Hakkında (2), aynı zamanda katılmıyorum: genel olarak, bir "iki yönlü ilişki" mutasyona dik bir matematiksel kavramdır. Genellikle Java'da uygulandığı gibi değişkenlik gerektirir (bu noktada sizinle aynı fikirdeyim). Bununla birlikte, alternatif bir uygulama düşünebilirim: iki nesne arasında bir yapıcı ile ilişki sınıfı Relationship(a, b); ilişkileri yaratma noktasında, her iki tarafın a& bzaten var ve ilişki kendisi de sabittir. Bu yaklaşımın Java'da pratik olduğunu söylemiyorum; Sadece mümkün.
Andres F.

4
Eğer, dediğini dayalı @AndresF. Yani, Rolup Relationship(a,b)hem ave bdeğişmez olduğu, ne ade bbir başvuru yapacağını R. Bunun çalışması için referansın başka bir yerde saklanması gerekir (statik bir sınıf gibi). Niyetini doğru anlıyor muyum?
smartcaveman

9
Chthulhu tembellik ile işaret ettiğinden, değişken veriler için çift yönlü bir ilişki depolamak mümkündür. Bunu yapmanın bir yolu: haskell.org/haskellwiki/Tying_the_Knot
Thomas Eding

36

"Tamamen işlevsel veri yapıları" okudum ve değişken nesneler kullanarak uygulanması çok daha kolay olan birkaç veri yapısının olduğunu fark etmemi sağladı.

İkili arama ağacını uygulamak için, her seferinde yeni bir ağaç döndürmeniz gerekir: Yeni ağacınız, değiştirilen her düğümün bir kopyasını çıkarmak zorunda kalacak (değiştirilmemiş dallar paylaşılır). Ekleme işleviniz için bu çok kötü değil, ama benim için, silme ve yeniden dengeleme üzerinde çalışmaya başladığımda işler hızla oldukça etkisizleşti.

Gerçekleştirmesi gereken bir diğer şey ise, yıllarca nesneye yönelik kod yazmaya devam edebilmeniz ve eğer kodunuz eşzamanlılık problemlerini ortaya çıkaracak şekilde çalıştırılmamışsa, paylaşılan değişken durumun ne kadar korkunç olabileceğini asla bilemeyeceğinizdir.


3
Bu Okasaki kitabı mı?
Mekanik salyangoz,

Evet. biraz kuru ama bir sürü iyi bilgi ...
Paul Sanwald

4
Komik, her zaman Okasakis kırmızı / siyah ağacının çok daha basit olduğunu düşündüm. 10 satır ya da öylesine. Sanırım en büyük avantaj, eski sürümü de aynı şekilde tutmak istediğinizde.
Thomas Ahle,

Son cümle geçmişte muhtemelen doğruyken, mevcut donanım eğilimleri vb
. Göz

29

Benim bakış açıma göre bu farkındalık eksikliği. Bilinen diğer JVM dillerine (Scala, Clojure) bakarsanız, değişken nesneler kodda nadiren görülür ve bu yüzden insanlar bunları tek diş açmanın yeterli olmadığı senaryolarda kullanmaya başlar.

Halen Clojure öğreniyorum ve Scala'da (Java'da da 4 yıl +) biraz deneyimim var ve kodlama tarzınız durum bilinci nedeniyle değişiyor.


Belki de "popüler" yerine "bilinen" kelimesi daha iyi bir seçim olacaktır.
Den

Evet bu doğru.
Florian Salihovic,

5
+1: Aynı fikirdeyim: Scala ve Haskell'i öğrendikten sonra, her yerde Java'da final ve C ++ 'da const kullanma eğilimindeyim. Ayrıca, eğer mümkünse değişmez nesneler kullanıyorum ve değişken nesneler hala çok sık ihtiyaç duyulsa da, değişmez nesneleri ne sıklıkta kullanabildiğiniz şaşırtıcı.
Giorgio

5
Bu yorumumu iki buçuk yıl sonra okudum ve fikrim değişmezlik lehine değişti. Şu andaki projemde (Python'da) çok nadiren değişken nesneler kullanıyoruz. Kalıcı verilerimiz bile değişmez: bazı işlemlerin sonucu olarak yeni kayıtlar yaratıyoruz ve artık ihtiyaç olmadığında eski kayıtları siliyoruz, ancak diskteki hiçbir kaydı güncellemiyoruz. Söylemeye gerek yok, bu eşzamanlı, çok kullanıcılı uygulamamızın bugüne kadar uygulanması ve bakımı çok daha kolaylaştırdı.
Giorgio

13

Bir önemli bir faktör göz ardı edilmiştir düşünüyorum: Java Fasulye nesneleri mutasyona ve (özellikle kaynağın göz önünde bulundurarak) belirli bir stil temeline dayanmaktadır epeyce kişi almaya görünüyor bir (hatta olarak bir) kanonik örnek nasıl tüm Java yazılmalıdır.


4
+1, alıcı / ayarlayıcı deseni, ilk veri analizinden sonra bir tür varsayılan uygulama olarak çok sık kullanılır.
Jaap,

Bu muhtemelen büyük bir nokta ... "çünkü herkes böyle yapıyor" ... bu yüzden doğru olmalı. "Merhaba Dünya" programı için muhtemelen en kolay olanıdır. Nesne durumu değişikliklerini, "Merhaba Dünya" anlayışının derinliklerinden biraz daha zor olan, değişken özelliklere sahip bir ... ... değişimle gerçekleştirin. 20 yıl sonra, 20. yüzyıl programlamasının zirvesinin, herhangi bir yapıya sahip olmayan bir nesnenin her niteliği üzerine getX ve setX yöntemleri (ne kadar sıkıcı) yazmak olduğuna çok şaşırdım. % 100 değişkenlikle kamuya doğrudan erişime sadece bir adım uzaklıktadır.
Darrell Teague

12

Kariyerim boyunca çalıştığım her kurumsal Java sistemi, Hazırda Beklet veya Java Kalıcılık API'sını (JPA) kullanır. Hazırda Bekletme ve JPA, esasen sisteminizin değiştirilebilir nesneler kullanmasını zorunlu kılar; çünkü bunların tüm önceliği, veri nesnelerinizde değişiklikleri algılamaları ve kaydetmeleridir. Pek çok proje için Hazırda Bekletme'nin getirdiği gelişme kolaylığı, değişmeyen nesnelerin faydalarından daha zorlayıcıdır.

Açıkçası, değişebilen nesneler Hazırda Bekletme durumundan çok daha uzun süredir vardır, bu nedenle Hazırda Bekletme büyük olasılıkla değiştirilebilen nesnelerin popülerliğinin orijinal nedeni değildir. Belki değişken nesnelerin popülaritesi, Hazırda Bekletme'nin gelişmesine izin verdi.

Fakat bugün birçok küçük programcı, Hazırda Bekletme veya başka bir ORM kullanarak kurumsal sistemlerde dişlerini keserse, muhtemelen değişken nesneler kullanma alışkanlığını edineceklerdir. Hazırda Bekletme gibi çerçeveler değiştirilebilir nesnelerin popülaritesini koruyor olabilir.


Mükemmel nokta Her insan için her şey olması için, bu tür çerçevelerin çok az seçeneğe sahip olması, en düşük ortak paydaya düşmek, yansıma tabanlı vekilleri kullanmak ve esneklik için yol almak / ayarlamaktır. Elbette bu, devlet geçiş kuralları çok az olan veya hiç maalesef uygulamak için ortak bir araç olmayan sistemler oluşturur. Pek çok projeden sonra uygunluk, genişletilebilirlik ve doğruluk için neyin daha iyi olduğu konusunda tam olarak emin değilim. Melez düşünmeye meyilliyim. Dinamik ORM iyiliği ancak hangi alanların gerekli olduğu ve hangi durum değişikliklerinin mümkün olması gerektiği ile ilgili bazı tanımlamalar.
Darrell Teague

9

Henüz belirtilmeyen önemli bir noktası, bir nesnenin durumunu kesilebilir olması olan mümkün kılmasıdır olan kimlik durum değişmez olması kapsüller nesne.

Birçok program, doğal olarak değişken olan gerçek dünyadaki şeyleri modellemek için tasarlanmıştır. Saat 12: 51'de, bazı değişkenlerin AllTrucks, bir filonun o andaki (12:51) tüm kamyonlarında hangi yükün bulunduğunu gösteren bir veri yapısının kökü olan # 451 nesnesine bir başvuruda bulunduğunu varsayalım. BobsTruck# 24601 nesnesine bir referans almak için kullanılabilir, o anda Bob'un kamyonunda hangi yükün bulunduğunu gösteren bir nesneyi gösterir (12:51). Saat 12: 52'de, bazı kamyonlar (Bob's dahil) yüklenir ve boşaltılır ve veri yapıları güncellenir, böylece AllTrucksşimdi kargo 12: 52'den itibaren tüm kamyonlarda olduğunu gösteren bir veri yapısına referans olacaktır.

Ne olmalı BobsTruck?

Eğer her bir kamyon nesnesinin 'cargo' özelliği değişmez ise, o zaman # 24601 no.lu nesne, Bob'un kamyonunun saat 12: 51'de sahip olduğu durumu temsil eder. Eğer BobsTruck# 24601 nesne doğrudan başvuru tutan güncelleyen kod sürece, daha sonra AllTrucksda güncellemek olur BobsTruck, Bülent'in kamyonun mevcut durumunu temsil sona erecek. Ayrıca BobsTruck, bir değişebilir nesne biçiminde saklanmadıkça, güncelleme yapan kodun güncellenebilmesinin tek yolu, kodun AllTrucksbunu yapmak için açıkça programlanmış olmasından kaynaklanabileceğini unutmayın.

Eğer kişi BobsTrucktüm nesneleri değişmez tutarken Bob'un kamyonunu gözlemlemek için kullanabilmek isterse , herhangi bir zamanda veya belirli bir zamanda sahip BobsTruckolduğu değere göre AllTrucks, Bob'un kamyonunun durumunu verecek olan değiştirilemez bir fonksiyon olabilir . o zaman. Biri, biri yukarıda olduğu gibi, diğeri bir filo devletine ve yeni bir kamyon durumuna referans kabul eden ve yeni bir filo durumuna referans veren bir çift değişmez fonksiyona sahip olabilir. eskisi ile eşleşti, ancak Bob'un kamyonu yeni bir duruma sahip olacaktı.

Ne yazık ki, Bob'un kamyonunun durumuna erişmek istediği her seferinde böyle bir işlevi kullanmak zorunda kalmak, sinir bozucu ve hantal hale gelebilir. Alternatif bir yaklaşım, # 24601 nesnesinin her zaman ve sonsuza dek (birileri referans aldığı sürece) Bob'un kamyonunun şu anki durumunu temsil edeceğini söylemek olacaktır . Bob'un kamyonunun mevcut durumuna art arda erişmek isteyecek olan kod, her zaman zaman alan bir işlevi çalıştırmak zorunda kalmayacaktı, bu nesnenin Bob'un kamyonu olduğunu bulmak için bir kez sadece bir arama işlevi yapabilirdi ve sonra basitçe Bob'un kamyonunun şu anki durumunu görmek istediği zaman bu nesneye eriş.

İşlevsel yaklaşımın, tek dişli bir ortamda veya dişlerin çoğunlukla onu değiştirmek yerine yalnızca verileri gözlemleyeceği çok dişli bir ortamda avantajsız olmadığını unutmayın. İçinde bulunan nesne referansını kopyalayan herhangi bir gözlemci ipliğiAllTrucksve ardından temsil edilen kamyon durumlarını inceler, böylece referansı aldığı andan itibaren tüm kamyonların durumunu görür. Bir gözlemci iş parçacığı daha yeni verileri görmek istediğinde, başvuruyu yeniden alabilir. Öte yandan, tek bir değişmez nesne ile temsil edilen filonun tüm durumuna sahip olmak, aynı anda farklı kamyonları aynı anda güncelleyen iki ipliğin bulunmasını engelleyecektir, çünkü her bir iplik kendi cihazlarına bırakıldığında, dahil olan yeni bir "filo durumu" nesnesi üretecektir. kamyonunun yeni hali ve birbirlerinin eski halleri. Her bir iş parçacığı yalnızca değişmediyse CompareExchangegüncelleme yapmak AllTrucksiçin kullanırsa ve başarısız olmuşsa yanıtlarsa, doğruluk sağlanabilirCompareExchangedurum nesnesini yenilemek ve işlemi yeniden denemekle birlikte, birden fazla iş parçacığı eşzamanlı bir yazma işlemi yapmaya çalışırsa, performans genellikle tek bir iş parçacığında tüm yazı yazılmasından daha kötü olacaktır; ne kadar çok iş parçacığı bu tür eşzamanlı işlemleri denerse, performans o kadar kötü olur.

Tek tek kamyon nesneleri değişken ise ancak değişken kimlikleri varsa , çok iş parçacıklı senaryo daha temiz hale gelir. Herhangi bir kamyonda bir seferde yalnızca bir ipliğin çalışmasına izin verilebilir, ancak farklı kamyonlarda çalışan ipliğin parazitsiz yapılabilmesi mümkündür. Değişmez nesneler kullanırken bile böyle bir davranışı taklit etmenin yolları olsa da (örneğin, biri "AllTrucks" nesnelerini tanımlayabilir, böylelikle XXX'a ait kamyonun SSS'ye ayarlanması durumu basitçe bir nesnenin oluşturulmasını gerektirir. [XXX] 'a ait kamyonun durumu şimdi [SSS]; her şeyin durumu [AllTrucks’ın eski değeri] ". Böyle bir nesneyi oluşturmak, çekişme durumunda bile yeterince hızlı olacaktı.CompareExchangedöngü uzun sürmezdi. Öte yandan, böyle bir veri yapısının kullanılması, belirli bir kişinin kamyonunu bulmak için gereken süreyi büyük ölçüde arttıracaktır. Değişmez kimlikleri olan değişken nesneler kullanmak bu sorunu önler.


8

Doğru ya da yanlış yok, sadece ne istediğine bağlı. Bazı insanların bir paradigmayı diğerine, diğeri veri modelini tercih eden dilleri tercih etmesinin bir nedeni var. Bu sadece sizin tercihinize ve ne elde etmek istediğinize bağlı (ve her iki yaklaşımı da bir taraf veya diğer tarafın sert taraftarlarını yabancılaştırmadan rahatça kullanabilmek, bazı dillerin peşinde olduğu kutsal bir kâsedir).

Bence sorunuza cevap vermenin en hızlı ve en iyi yolu , Mutability ve Mutabilite ile Artıları ve Eksileri Eksenleri'ne yönelmenizdir .


7

Bu blog gönderisine bakın: http://www.yegor256.com/2014/06/09/objects-should-be-immutable.html . Değişmez nesnelerin neden değişkenden daha iyi olduklarını özetler. İşte argümanların kısa bir listesi:

  • değişmez nesnelerin oluşturulması, test edilmesi ve kullanılması daha kolaydır
  • gerçekten değişken nesneler her zaman iş parçacığı için güvenlidir
  • geçici kaplin oluşumunu önlemeye yardımcı olurlar
  • kullanımları yan etki içermez (savunma kopyası yoktur)
  • kimlik değişebilirliği probleminden kaçınılır
  • her zaman başarısızlık atomitesi var
  • önbelleklemesi çok daha kolaydır

İnsanlar anlayabildiğim kadar değişken nesneler kullanıyorlar çünkü hala OOP'yi zorunlu prosedürel programlama ile karıştırıyorlar.


5

Java'da değişmez nesneler, nesnenin tüm özelliklerini alacak bir yapıcı gerektirir (veya yapıcı bunları başka argümanlardan veya varsayılanlardan oluşturur). Bu özellikler olmalıdır işaretlenecektir son .

Bununla ilgili çoğunlukla veri bağlama ile ilgili dört problem vardır :

  1. Java Yapıcıları meta verilerini yansıtma argüman adlarını korumaz.
  2. Java Yapıcıları (ve yöntemleri), adlandırılmış parametrelere (etiket olarak da adlandırılır) sahip değildir, bu nedenle birçok parametreyle karıştırır.
  3. Bir başka değişmez nesne miras alırken, uygun bir kurucu sırası çağrılmalıdır. Bu, alanlardan birini nihai olmayan bırakma ve bırakma noktasında oldukça zor olabilir.
  4. Çoğu ciltleme teknolojisi (Spring MVC Veri Bağlama, Hazırda Bekletme vb. Gibi) yalnızca bağımsız değişken oluşturucularla çalışır (bunun nedeni açıklamaların her zaman bulunmamasıydı).

@ConstructorPropertiesDeğişmeyen nesneyi oluşturmak için başka bir değiştirilebilir oluşturucu nesne (genellikle akıcı) gibi ek açıklamalar kullanarak ve bunları değiştirerek # 1 ve # 2 değerini azaltabilirsiniz .


5

Performans iyileştirme avantajlarından kimsenin bahsetmediğinden şaşırdım. Dile bağlı olarak, derleyici değişmez verilerle uğraşırken bir sürü optimizasyon yapabilir, çünkü verilerin asla değişmeyeceğini bilir. Her türlü malzeme atlanır ve bu da size olağanüstü performans avantajları sağlar.

Ayrıca değişmez nesneler neredeyse bütün devlet hata sınıfını ortadan kaldırır.

Olması gerektiği kadar büyük değil, çünkü zor, her dile uygulanmaz ve çoğu kişiye zorunlu kodlama öğretildi.

Ayrıca çoğu programcının kutusunda mutlu olduğunu ve çoğu zaman tam olarak anlamadıkları yeni fikirlere karşı dirençli olduklarını keşfettim. Genelde insanlar değişmekten hoşlanmaz.

Ayrıca, çoğu programcının durumunun kötü olduğunu da unutmayın. Vahşi doğada yapılan çoğu programlama korkunç ve bunun bir anlayış ve politika eksikliğinden kaynaklanıyor.


4

İnsanlar neden herhangi bir güçlü özellik kullanıyor? İnsanlar neden meta-programlama, tembellik veya dinamik yazmayı kullanıyor? Cevap kolaylıktır. Değişken devlet çok kolaydır. Güncellemesi o kadar kolaydır ve değişmez durumun çalışılabilir durumdan daha üretken olduğu proje büyüklüğü eşiği oldukça yüksektir, bu yüzden seçim bir süredir sizi ısırmaz.


4

Programlama dilleri bilgisayarlar tarafından yürütülecek şekilde tasarlanmıştır. Tüm önemli bilgisayar blokları - CPU, RAM, önbellek, diskler - değişkendir. Bunlar olmadığında (BIOS), onlar gerçekten değişken değildir ve siz de yeni değişmez nesneler yaratamazsınız.

Bu nedenle, değişmez nesnelerin üzerine inşa edilen herhangi bir programlama dili, uygulamasında bir temsil boşluğu çekmektedir. Ve C gibi erken diller için, bu büyük bir engeldi.


1

Değişken nesneler olmadan devletiniz olmaz. Kuşkusuz, bunu yönetebiliyorsanız ve bir nesneye birden fazla iş parçacığından referans verilme olasılığı varsa, bu iyi bir şeydir. Ancak program oldukça sıkıcı olacak. Bir çok yazılım, özellikle web sunucuları, veritabanları, işletim sistemleri, sistem kütüphaneleri, vb. Üzerinde değişkenliği ortadan kaldırarak değişken nesnelerin sorumluluğunu almaktan kaçınır. Pratik bir mesele olarak, programcıyı değişkenlik problemlerinden kurtarır ve web (ve diğer) uygun fiyatlı. Fakat değişkenlik hala orada.

Genel olarak, üç tür sınıfa sahipsiniz: dikkatlice korunmaları ve korunmaları gereken normal, iş parçacığı güvenli olmayan sınıflar; serbestçe kullanılabilen değişmez sınıflar; ve serbestçe kullanılabilen ancak aşırı dikkatle yazılması gereken değişken, güvenli dişliler. İlk tip, sorunlu olandır, en kötüsü üçüncü tip olduğu düşünülenlerdir . Tabii ki, ilk tip yazmak kolay olanlardır.

Genelde, dikkatlice izlemem gereken birçok normal, değişken sınıfla karşılaşıyorum. Çok iş parçacıklı bir durumda, gerekli senkronizasyon, ölümcül bir kucaklaşmadan kaçınabildiğimde bile her şeyi yavaşlatıyor. Bu yüzden, genellikle değişebilir sınıfın değişmez kopyalarını yapıyorum ve bunları kullanabilecek kişilere teslim ediyorum. Orignal mutasyonların her seferinde yeni bir değişmez kopya gereklidir, bu yüzden zaman zaman orjinalinin yüzlerce kopyasına sahip olduğumu hayal ediyorum. Ben tamamen Çöp Toplama'ya bağımlıyım.

Özetle, çoklu iş parçacığı kullanmıyorsanız, iş parçacığı güvenli olmayan değiştirilebilir nesneler iyidir. (Ancak çok iş parçacığı her yere yayılıyor - dikkatli olun!) Yerel değişkenlerle kısıtlarsanız veya bunları titizlikle senkronize ederseniz, güvenle kullanılabilirler. Bunları başkalarının kanıtlanmış kodunu (DB'ler, sistem çağrıları, vb.) Kullanarak önleyebilirsiniz. Eğer varsa olabilir değişmez bir sınıfını kullanın Bunu yapmak. Ve bence , genel olarak insanlar ya çok iş parçacığı sorunlarından habersizler ya da (duyusal olarak) korkutuyorlar ve çok iş görmekten kaçınmak için her türlü hileyi kullanıyorlar (veya bunun yerine başka bir yere sorumluluk yüklüyorlar).

Bir PS olarak, Java alıcılarının ve ayarlayıcılarının kullanımdan çıktığını hissediyorum. Kontrol bu dışarı.


7
Değiştirilemez durum hala devlettir.
Jeremy Heiler,

3
@JeremyHeiler: Doğru, ama bir şeyin devlet var olduğu değişken. Eğer hiçbir şey değişmezse, hiçbir devlet ile aynı şey olmayan tek bir devlet vardır.
RalphChapin

1

Birçok insanın iyi cevapları vardı, bu yüzden dokunduğun bir şeye dikkat çekmek istedim, çok gözlemciydi ve son derece doğru ve burada başka bir yerde bahsedilmedi.

Ayarlayıcıları ve alıcıları otomatik olarak oluşturmak korkunç, korkunç bir fikirdir ancak yine de prosedürel düşünenlerin OO'yu zihniyetlerine zorlamaya çalıştıkları ilk yoldur. Ayarlayıcılar ve alıcılar, özelliklerle birlikte, yalnızca gereksinim duyduğunuzda her varsayılan ayar için değil

Aslında, düzenli olarak alıcılara ihtiyaç duymanıza rağmen, ayarlayıcıların veya yazılabilir özelliklerin kodunuzda var olması gereken tek yol, nesnenin tamamen başlatılmasından sonra kilitlendikleri bir oluşturucu paternidir.

Birçok sınıf yaratıldıktan sonra değişkendir, sadece özelliklerinin doğrudan manipüle edilmemesi gerekir - bunun yerine özelliklerini gerçek iş mantığına sahip yöntem çağrıları yoluyla manipüle etmesi istenir (Evet, bir ayarlayıcı hemen hemen aynıdır) doğrudan özellik manipüle gibi şey)

Şimdi bu gerçekten "Scripting" stil kodu / dilleri için geçerli değil, başkaları için yarattığınız kod için ve başkalarının yıllar içinde tekrar tekrar okumasını beklemeniz için geçerli değildir. Son zamanlarda bu ayrımı yapmaya başlamam gerekti, çünkü Groovy ile uğraşmaktan çok zevk alıyorum ve hedeflerde büyük bir fark var.


1

Değiştirilebilir nesneler, nesneyi başlattıktan sonra katları değerlerini ayarlamanız gerektiğinde kullanılır.

Örneğin altı parametreli bir kurucunuz olmamalıdır. Bunun yerine nesneyi setter yöntemleriyle değiştirirsiniz.

Buna örnek olarak font, oryantasyon vb. Ayarlayıcıları olan bir Report nesnesidir.

Kısacası: değişkenler, bir nesneye ayarlanacak çok fazla devletiniz olduğunda ve çok uzun bir kurucu imzanın olması pratik olmazsa kullanışlıdır.

EDIT: Oluşturucu deseni, nesnenin bütün durumunu oluşturmak için kullanılabilir.


3
bu değişkenlik ve somutlaştırmadan sonraki değişiklikler gibi çoklu değerleri ayarlamak için tek yol olarak sunulmaktadır. Bütünlüğün iyiliği için, Oluşturucu deseninin eşit veya daha güçlü yetenekler sunduğunu ve değişmezliğin fedakarlık edilmesini gerektirmediğini unutmayın. new ReportBuilder().font("Arial").orientation("landscape").build()
tatarcık

1
"Çok uzun bir yapıcı imzasına sahip olmak pratik olmaz.": Parametreleri her zaman daha küçük nesnelere gruplandırabilir ve bu nesneleri yapıcıya parametre olarak iletebilirsiniz.
Giorgio,

1
@cHao 10 veya 15 nitelik ayarlamak istersen? Ayrıca, bir yöntemin withFontdöndürdüğü iyi görünmüyor Report.
Tulains Córdova

1
(1) Java, tüm bu ara nesnelerin yapısını nasıl seçeceğini ve eğer (2) yine isimlerin standart hale getirildiğini bilseydi, 10 veya 15 niteliğini belirlerken, bunu yapmak zor olmazdı. Değişmezlikle ilgili bir sorun değil; Java ile nasıl yapılacağını bilmemek bir problemdir.
cHao

1
@cHao 20 özellik için bir çağrı zinciri yapmak çok çirkin. Çirkin kod, düşük kaliteli kod olma eğilimindedir.
Tulains Córdova

1

Değişken nesnelerin kullanılmasının zorunlu düşünceden kaynaklandığını düşünüyorum: değişken değişkenlerin içeriğini adım adım değiştirerek bir sonucu hesaplarsınız (yan etki ile hesaplama).

İşlevsel olarak düşünürseniz, değişmez duruma sahip olmak ve işlevleri uygulayarak ve eskilerinden yeni değerler yaratarak sistemin sonraki hallerini temsil etmek istersiniz.

İşlevsel yaklaşım daha temiz ve daha güçlü olabilir, ancak kopyalama nedeniyle çok verimsiz olabilir, böylece artımlı olarak değiştirdiğiniz paylaşılan veri yapısına geri dönmek istiyorsunuz.

En makul bulduğum takas şu: Değişmez nesnelerle başlayın ve uygulamanız yeterince hızlı değilse değiştirilebilir nesnelere geçin. Bu bakış açısına göre, değişken nesnelerin sistematik olarak baştan kullanılması bir tür erken optimizasyon olarak düşünülebilir: en baştan daha verimli (ancak bunu anlamak ve hata ayıklamak için daha zor) bir uygulamayı seçersiniz.

Peki, neden birçok programcı değişken nesneler kullanıyor? IMHO iki nedenden dolayı:

  1. Birçok programcı, zorunlu (usule dayalı veya usule dayalı) bir paradigma kullanarak nasıl programlanacağını öğrenmiştir, bu nedenle değişkenlik, hesaplamanın tanımlanmasında temel yaklaşımdır, yani ne zaman ve nasıl kullanılacağını bilmedikleri için, aşina olmadıklarını bilmezler.
  2. Pek çok programcı, performans konusunda çok erken endişe duymaktadır; ancak, öncelikle işlevsel olarak doğru bir program yazmaya odaklanmak ve ardından darboğazları bulmaya ve en iyi duruma getirmeye çalışmak daha etkilidir.

1
Mesele sadece hız değil. Değişken türleri kullanmadan basitçe uygulanamayan birçok faydalı yapı türü vardır. Diğer şeylerin yanı sıra, iki iplik arasındaki iletişim, mutlak asgari olarak, her ikisinin de birisinin veri koyabileceği ve diğerinin okuyabileceği paylaşılan bir nesneye referansa sahip olmasını gerektirir. Ayrıca, "Bu nesneyi al," Bu nesnenin özelliklerini değiştir P ve Q "demek," Bu nesneyi al, P'nin değeri dışında onun gibi olan yeni bir nesneyi inşa et "den daha çok anlamlıdır. sadece Q hariç böyle. "
Süper kedi

1
Bir FP uzmanı değilim ama AFAIK (1) iş parçacığı iletişimi, bir iş parçacığında değişmez bir değer oluşturarak ve bir başkasını okuyarak (yine, AFAIK, bu Erlang yaklaşımıdır) (2) AFAIK bir mülk belirleme gösterimi fazla değişmez (örneğin Haskell setProperty kayıt değeri, Java record.setProperty (değer) değerine karşılık gelir), yalnızca anlamsal değerler değişir, çünkü bir özellik ayarlamanın sonucu yeni bir değişken kayıttır.
Giorgio,

1
"her ikisi de birisinin veri koyabileceği ve diğerinin okuyabileceği paylaşılan bir nesneye başvuruda bulunmalıdır": daha doğrusu, nesneyi değişmez hale getirebilir (tüm üyeler C ++ 'da const veya Java'da final) ve tüm içeriği yapıcı. Daha sonra bu değişmez nesne üretici ipliğinden tüketici ipliğine verilir.
Giorgio,

1
(2) Performansı, değişmez durumu kullanmamak için bir neden olarak listeledim. Tabii ki (1) ile ilgili olarak, konuların arasındaki iletişimi uygulayan mekanizma, değişken bir duruma ihtiyaç duyar, ancak bunu programlama modelinizden gizleyebilirsiniz, bakınız örn. Aktör modeli ( en.wikipedia.org/wiki/Actor_model ). Dolayısıyla, daha düşük bir seviyede iletişimi uygulamak için değişkenliğe ihtiyaç duysanız bile, içinde değişmez nesneler gönderen dişler arasında iletişim kurduğunuz bir üst soyutlama seviyesine sahip olabilirsiniz.
Giorgio,

1
Sizi tam olarak anladığımdan emin değilim, ancak her değerin değişmez olduğu saf bir işlevsel dil bile, tek bir değişken şey var: program durumu, yani mevcut program yığını ve değişken bağlamalar. Ancak bu uygulama ortamıdır. Her neyse, bunu bir süre sohbette tartışıp sonra bu sorudan gelen mesajları temizlemenizi öneririm.
Giorgio,

1

Java hakkında soru sorduğunu biliyorum, ama objektif-c'de her zaman değişmez vs değişmez kullanıyorum. Değişmez bir dizi NSArray ve değişken bir dizi NSMutableArray vardır. Bunlar, kesin kullanımı ele almak için özel olarak optimize edilmiş bir şekilde yazılmış iki farklı sınıftır. Bir dizi oluşturmanız ve içeriğini asla değiştirmem gerekmiyorsa, daha küçük bir nesne olan NSArray'i kullanırdım ve değişken bir diziye kıyasla daha hızlı bir şekilde yapardım.

Dolayısıyla, değişmeyen bir Person nesnesi oluşturursanız, o zaman sadece bir kurucu ve alıcılara ihtiyacınız olur, bu nedenle nesne daha küçük olacak ve daha az bellek kullanacaktır, bu da programınızı gerçekten daha hızlı hale getirecektir. Oluşturulduktan sonra nesneyi değiştirmeniz gerekirse, değişken bir Person nesnesi daha iyi olacaktır, böylece yeni bir nesne oluşturmak yerine değerleri değiştirebilir.

Yani: Nesne ile ne yapmayı planladığınıza bağlı olarak, değişken veya değişken olan değişkenleri seçmek, performans söz konusu olduğunda büyük bir fark yaratabilir.


1

Burada verilen diğer birçok nedene ek olarak, bir sorun, ana dillerin değişmezliği iyi desteklememesidir. En azından, const veya final gibi ek anahtar kelimeler eklemek zorunda olduğunuz ve çok sayıda argüman veya kod uzun oluşturucu desenleri olan okunaksız yapıcılar kullanmanız gerektiği için değişmezlik için ceza alırsınız.

Akılda kalıcılık ile yapılan dillerde bu çok daha kolay. İsteğe bağlı olarak adlandırılmış bağımsız değişkenlerle bir sınıf Kişisi tanımlamak ve değiştirilmiş bir niteliğe sahip bir kopya oluşturmak için bu Scala kod parçasını göz önünde bulundurun:

case class Person(id: String, firstName: String, lastName: String)

val joe = Person("123", "Joe", "Doe")
val spouse = Person(id = "124", firstName = "Mary", lastName = "Moe")
val joeMarried = joe.copy(lastName = "Doe-Moe")

Dolayısıyla, geliştiricilerin değişmezliği benimsemelerini istiyorsanız, bu neden daha modern bir programlama diline geçmeyi düşünebileceğinizin sebeplerinden biridir.


Bu, önceki 24
cevapta

@gnat Önceki cevaplardan hangisi, anadil dillerinin çoğunun değişkenliği iyi desteklemediğinin altını çiziyor? Bence bu nokta henüz yapılmamıştır (kontrol ettim), ama bu IMHO için oldukça önemli bir engel.
Hans-Peter Störr

bu bir örnek Java bu konuyu açıklayan derinlere iner. Ve en az 3 diğer cevap da dolaylı olarak
ilgiliydi

0

Değişmez, değeri değiştiremeyeceğiniz anlamına gelir ve değişken, ilkel ve nesneler açısından düşünüyorsanız, değeri değiştirebileceğiniz anlamına gelir. Nesneler, Java'daki ilkellerden farklıdır, çünkü bunlar türlerde yerleşiktir. İlkel karakterler int, boolean ve void gibi tiplerde üretilirler.

Bir çok insan, ilkel bir değiştiriciye sahip olan ilkellerin ve nesnelerin değişkenlerinin önlerinde değişmez olduğunu düşünüyor, ancak bu tam olarak doğru değil. Yani final neredeyse değişkenler için değişmez anlamına gelmez. Bir kod örneği için bu bağlantıya göz atın :

public abstract class FinalBase {

    private final int variable; // Unset

    /* if final really means immutable than
     * I shouldn't be able to set the variable
     * but I can.
     */
    public FinalBase(int variable) { 
        this.variable = variable;
    }

    public int getVariable() {
        return variable;
    }

    public abstract void method();
}

// This is not fully necessary for this example
// but helps you see how to set the final value 
// in a sub class.
public class FinalSubclass extends FinalBase {

    public FinalSubclass(int variable) {
        super(variable);
    }

    @Override
    public void method() {
        System.out.println( getVariable() );
    }

    @Override
    public int getVariable() {

        return super.getVariable();
    }

    public static void main(String[] args) {
        FinalSubclass subclass = new FinalSubclass(10);
        subclass.method();
    }
}

-1

Arayüz pencereleri gibi "gerçek hayat" değişken "nesneleri" modellemek için iyi bir neden olacağını düşünüyorum. Birisi bazı kargo liman operasyonlarını kontrol etmek için bir yazılım yazmayı denediğinde OOP'un icat edildiğini okuduğumu belli belirsiz hatırlıyorum.


1
OOP'un kökenleri hakkında bunu nereden okuduğumu henüz bulamıyorum, ancak Wikipedia'ya göre , büyük bir konteyner nakliye şirketi OOCL'nin bazı Bütünleşik Bölgesel Bilgi Sistemi Smalltalk'ta yazıyor.
Alexey

-2

Java, çoğu durumda değişken nesneleri zorunlu kılar, örneğin, bir ziyaretçide veya çalıştırılabilir bir şeyi saymak veya iade etmek istediğinizde, çoklu kullanım olmadan bile, son değişkenlere ihtiyacınız vardır.


5
finalaslında değişmezliğe doğru bir adımın yaklaşık 1 / 4'ü . Neden bahsettiğini görmemek.
cHao

yazımı gerçekten okudun mu
Ralf H,

Aslında soruyu okudun mu? :) Kesinlikle ilgisi yoktu final. Bu bağlamda ortaya çıkarmak, asıl finalmesele belirli mutasyon türlerini önlemekfinal olduğu zaman, "değişebilir" ile gerçekten garip bir birleşime yol açar . (BTW, benim olumsuz oyum değil.)
cHao

Burada bir yerde geçerli bir nokta olmadığını söylemiyorum. Çok iyi açıklayamadığını söylüyorum. Muhtemelen onunla nereye gittiğini anlamam gerek, ama daha ileri gitmen gerekiyor. Olduğu gibi, sadece karışık görünüyor.
cHao

1
Değişken bir nesnenin gerekli olduğu aslında çok az sayıda durum vardır . Değişken nesneler kullanarak kodun daha net veya bazı durumlarda daha hızlı olacağı durumlar vardır. Ancak, tasarım modellerinin büyük çoğunluğunun, temelde, onu desteklemeyen diller için sadece işlevsel bir yarı program sunumu olduğunu düşünün. Bunun eğlenceli kısmı, FP sadece çok seçili yerlerde (yani, yan etkilerin oluşması gereken yerlerde) değişkenlik gerektirir ve bu yerler genellikle sayı, boyut ve kapsam bakımından sıkıca sınırlıdır.
cHao
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.