it-swarm-tr.com

Java neden operatöre aşırı yükleme yapmıyor?

C++ 'dan Java' ya gelince, açık cevapsız soru Java neden operatörün aşırı yüklenmesini içermiyordu?

Complex a, b, c; a = b + c;, Complex a, b, c; a = b.add(c);'dan daha basit değil mi?

Bunun bilinen bir nedeni var mı, değil operatörün aşırı yüklenmesine izin vermek için geçerli argümanlar var mı? Sebep keyfi mi yoksa zaman kaybı mı?

375
rengolin

a tarafından belirtilen nesnenin önceki değerinin üzerine yazmak istediğinizi varsayarak, bir üye işlevinin çağrılması gerekir.

Complex a, b, c;
// ...
a = b.add(c);

C++ 'da, bu ifade derleyiciye istif üzerinde üç (3) nesne yaratmasını, toplama işlemini gerçekleştirmesini ve kopyala elde edilen değeri geçici nesneden varolan nesneye a içine bildirmesini söyler.

Ancak, Java'da operator=, başvuru türleri için değer kopyası yapmaz ve kullanıcılar, değer türleri değil, yalnızca yeni başvuru türleri oluşturabilir. Dolayısıyla Complex adlı kullanıcı tanımlı bir tür için atama, var olan bir değere bir başvuru kopyalamak anlamına gelir.

Bunun yerine düşünün:

b.set(1, 0); // initialize to real number '1'
a = b; 
b.set(2, 0);
assert( !a.equals(b) ); // this assertion will fail

C++ 'da, bu değeri kopyalar, böylece karşılaştırma eşit olmaz. Java'da, operator= referans kopyasını çıkarır, böylece a ve b şimdi aynı değere işaret eder. Sonuç olarak, nesne 'eşit' olacağı için karşılaştırma 'eşit' üretecektir.

Kopyalar ve referanslar arasındaki fark, sadece operatör aşırı yüklenmesinin karışıklığına neden olur. @Sebastian'ın belirttiği gibi, Java ve C #, her ikisi de değer ve referans eşitliği ile ayrı ayrı ilgilenmek zorundadır - operator+ muhtemelen değer ve nesnelerle ilgilenir, ancak operator= zaten referanslarla ilgilenmek için zaten uygulanmıştır.

C++ 'da, bir seferde yalnızca bir karşılaştırma yapmalısınız, bu yüzden daha az kafa karıştırıcı olabilir. Örneğin, Complex'da operator= ve operator== hem değerler üzerinde çalışmaktadır - sırasıyla değerleri kopyalamak ve değerleri karşılaştırmak.

17
Aaron

Operatör aşırı yüklenmesinden şikayet eden birçok mesaj var.

"Operatör aşırı yükleme" kavramlarını netleştirmek zorunda olduğumu, bu kavram üzerinde alternatif bir bakış açısı sunduğumu hissettim.

Kod engelleyici mi?

Bu argüman bir yanlıştır.

Her dilde kafa karıştırıcı olabilir ...

Kodları C veya Java ile gizlemek, C++ 'ta olduğu gibi, operatör aşırı yüklenmeleri ile olduğu kadar kolaydır:

// C++
T operator + (const T & a, const T & b) // add ?
{
   T c ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

// Java
static T add (T a, T b) // add ?
{
   T c = new T() ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

/* C */
T add (T a, T b) /* add ? */
{
   T c ;
   c.value = a.value - b.value ; /* subtract !!! */
   return c ;
}

... Java'nın standart arayüzlerinde bile

Başka bir örnek için, Java'da Cloneable interface 'i görelim:

Bu arayüzü uygulayan nesneyi klonlamanız gerekiyor. Ama yalan söyleyebilirsin. Ve farklı bir nesne yaratın. Aslında, bu arayüz o kadar zayıf ki, sadece eğlenmek için başka bir nesne türünü tamamen geri getirebilirsiniz:

class MySincereHandShake implements Cloneable
{
    public Object clone()
    {
       return new MyVengefulKickInYourHead() ;
    }
}

Cloneable arayüzü kötüye kullanılabiliyorsa/karıştırıldıysa, aynı gerekçelerle yasaklanmalı mıydı? C++ operatörünün aşırı yüklenmesi mi gerekiyor?

Günün yaylı saatini döndürmesi için MyComplexNumber sınıfının toString() yöntemini aşırı yükleyebiliriz. toString() aşırı yüklemesi de yasaklanmalı mı? Sabotajını yapabiliriz MyComplexNumber.equals rastgele bir değer döndürür, operandları değiştiririz… vb.

Java'da, C++ 'da olduğu gibi, ya da hangi dilde olursa olsun, programcının kod yazarken minimum bir anlambilimine saygı göstermesi gerekir. Bu, ekleyen add işlevini ve klonları oluşturan Cloneable uygulama yöntemini ve artımlardan daha fazla bir ++ işleci uygulamak anlamına gelir.

Zaten şaşırtan ne?

Artık kodun bozulmamış Java yöntemleriyle bile sabote edilebileceğini bildiğimize göre, C++ 'da operatör aşırı yüklenmesinin gerçek kullanımı hakkında kendimize sorabiliriz?

Net ve doğal gösterim: yöntemler vs. operatör aşırı yüklenmesi?

Aşağıda, hangi durumlarda kodlama stilinin daha net olduğu konusunda bir fikriniz olması için farklı durumlar için Java ve C++ 'daki "aynı" kodları karşılaştıracağız.

Doğal karşılaştırmalar:

// C++ comparison for built-ins and user-defined types
bool    isEqual          = A == B ;
bool    isNotEqual       = A != B ;
bool    isLesser         = A <  B ;
bool    isLesserOrEqual  = A <= B ;

// Java comparison for user-defined types
boolean isEqual          = A.equals(B) ;
boolean isNotEqual       = ! A.equals(B) ;
boolean isLesser         = A.comparesTo(B) < 0 ;
boolean isLesserOrEqual  = A.comparesTo(B) <= 0 ;

Lütfen A ve B'nin, operatör aşırı yükleri sağlandığı sürece, C++ 'ta herhangi bir türde olabileceğini unutmayın. Java'da, A ve B ilkel olmadığında, ilkel nesneler için bile (BigInteger, vb.) Kod çok kafa karıştırıcı olabilir ...

Doğal dizi/konteyner erişim sağlayıcıları ve abonelik:

// C++ container accessors, more natural
value        = myArray[25] ;         // subscript operator
value        = myVector[25] ;        // subscript operator
value        = myString[25] ;        // subscript operator
value        = myMap["25"] ;         // subscript operator
myArray[25]  = value ;               // subscript operator
myVector[25] = value ;               // subscript operator
myString[25] = value ;               // subscript operator
myMap["25"]  = value ;               // subscript operator

// Java container accessors, each one has its special notation
value        = myArray[25] ;         // subscript operator
value        = myVector.get(25) ;    // method get
value        = myString.charAt(25) ; // method charAt
value        = myMap.get("25") ;     // method get
myArray[25]  = value ;               // subscript operator
myVector.set(25, value) ;            // method set
myMap.put("25", value) ;             // method put

Java'da, her bir kabın aynı şeyi yapması için (içeriğine bir dizin veya tanımlayıcı aracılığıyla erişilir) görüyoruz, bunun için kafa karıştırıcı olan farklı bir yolumuz var.

C++ 'da, her konteyner operatör aşırı yüklemesi nedeniyle içeriğine erişmek için aynı yöntemi kullanır.

Doğal ileri tip manipülasyon

Aşağıdaki örnekler, Google'da bulunan ilk bağlantıları kullanarak bulunan "[ Java Matrix nesnesi " ve " c ++ Matrix nesnesi = için bulunan Matrix nesnesini kullanır. ":

// C++ YMatrix matrix implementation on CodeProject
// http://www.codeproject.com/KB/architecture/ymatrix.aspx
// A, B, C, D, E, F are Matrix objects;
E =  A * (B / 2) ;
E += (A - B) * (C + D) ;
F =  E ;                  // deep copy of the matrix

// Java JAMA matrix implementation (seriously...)
// http://math.nist.gov/javanumerics/jama/doc/
// A, B, C, D, E, F are Matrix objects;
E = A.times(B.times(0.5)) ;
E.plusEquals(A.minus(B).times(C.plus(D))) ;
F = E.copy() ;            // deep copy of the matrix

Ve bu matrislerle sınırlı değildir. BigInteger ve BigDecimal Java sınıfları aynı kafa karıştırıcı ayrıntılardan muzdariptir, oysa C++ 'daki eşdeğerleri yerleşik tipler kadar açıktır.

Doğal yineleyiciler:

// C++ Random Access iterators
++it ;                  // move to the next item
--it ;                  // move to the previous item
it += 5 ;               // move to the next 5th item (random access)
value = *it ;           // gets the value of the current item
*it = 3.1415 ;          // sets the value 3.1415 to the current item
(*it).foo() ;           // call method foo() of the current item

// Java ListIterator<E> "bi-directional" iterators
value = it.next() ;     // move to the next item & return the value
value = it.previous() ; // move to the previous item & return the value
it.set(3.1415) ;        // sets the value 3.1415 to the current item

Doğal functors:

// C++ Functors
myFunctorObject("Hello World", 42) ;

// Java Functors ???
myFunctorObject.execute("Hello World", 42) ;

Metin birleştirme:

// C++ stream handling (with the << operator)
                    stringStream   << "Hello " << 25 << " World" ;
                    fileStream     << "Hello " << 25 << " World" ;
                    outputStream   << "Hello " << 25 << " World" ;
                    networkStream  << "Hello " << 25 << " World" ;
anythingThatOverloadsShiftOperator << "Hello " << 25 << " World" ;

// Java concatenation
myStringBuffer.append("Hello ").append(25).append(" World") ;

Tamam, Java 'da MyString = "Hello " + 25 + " World" ; öğesini de kullanabilirsiniz ... Ama, bir saniye bekleyin: Bu operatör aşırı yüklenmesi, değil mi? Hile yapmıyor mu ???

:-D

Genel kod?

Aynı genel kod değiştiren işlenenler, hem yerleşik/ilkel (Java'da arabirimsiz) hem de standart nesneler (doğru arabirime sahip olmayan) ve kullanıcı tanımlı nesneler için kullanılabilir olmalıdır.

Örneğin, iki rasgele tür değerinin ortalama değerini hesaplamak:

// C++ primitive/advanced types
template<typename T>
T getAverage(const T & p_lhs, const T & p_rhs)
{
   return (p_lhs + p_rhs) / 2 ;
}

int     intValue     = getAverage(25, 42) ;
double  doubleValue  = getAverage(25.25, 42.42) ;
complex complexValue = getAverage(cA, cB) ; // cA, cB are complex
Matrix  matrixValue  = getAverage(mA, mB) ; // mA, mB are Matrix

// Java primitive/advanced types
// It won't really work in Java, even with generics. Sorry.

Operatör aşırı yüklenmesinin tartışılması

Şimdi operatör aşırı yüklemesini kullanan C++ kodu ile Java'daki aynı kod arasında adil karşılaştırmalar gördüğümüze göre, artık "operatör aşırı yüklemesi" kavramını tartışabiliriz.

Operatör aşırı yüklemesi, bilgisayarlardan önce gerçekleşti

Bilgisayar bilimi dışında bile, operatörün aşırı yüklenmesi var: Örneğin, matematikte, +, -, * vb. Operatörler aşırı yüklenmiştir.

Aslında, +, -, *, vb. İfadeleri işlenenlerin türlerine (sayısal, vektörler, kuantum dalga fonksiyonları, matrisler vb.) Bağlı olarak değişir.

Bilim derslerimizin bir parçası olarak çoğumuz, operand türlerine bağlı olarak operatörler için birçok anlam öğrendik. Onları kafa karıştırıcı bulduk mu?

Operatör aşırı yüklenmesi operatörlere göre değişir

Operatör aşırı yüklenmesinin en önemli kısmı budur: Matematik veya fizikte olduğu gibi, işlem operatörlerinin türüne bağlıdır.

Böylece, işlenenin türünü ve işlemin etkisini bileceksiniz.

C ve Java bile (sabit kodlanmış) operatörün aşırı yüklenmesi var

C de, bir operatörün gerçek davranışı, operatörlerine göre değişecektir. Örneğin, iki tamsayı eklemek, iki çift eklemek, hatta bir tamsayı ve bir çift olmaktan farklıdır. İşaretçi aritmetik alanının tamamı bile vardır (döküm yapmadan, işaretçiye bir tamsayı ekleyebilirsiniz, ancak iki işaretçi ekleyemezsiniz ...).

Java'da, işaretçi aritmetiği yoktur, ancak birisi + operatörü olmadan dize birleştirme işlemini hala buldu, "operatörün aşırı yüklenmesi kötü" inancının bir istisnasını haklı çıkaracak kadar saçma olurdu.

Sadece sen, C olarak (tarihsel nedenlerden dolayı) veya Java (için kişisel sebepler, aşağıya bakınız) kodlayıcı, kendiniz sağlayamazsınız.

C++ 'da, operatör aşırı yüklemesi isteğe bağlı değildir ...

C++ 'da yerleşik tipler için operatörün aşırı yüklenmesi mümkün değildir (ve bu iyi bir şeydir), fakat kullanıcı tanımlı türleri olabilir kullanıcı tanımlı Operatör aşırı yükleniyor.

Daha önce de belirtildiği gibi, C++ 'da ve Java'nın aksine, kullanıcı türleri, yerleşik türlerle karşılaştırıldığında, dilin ikinci sınıf vatandaşları olarak kabul edilmez. Bu nedenle, yerleşik türlerde operatör varsa, kullanıcı türlerinde de onlara sahip olması gerekir.

Gerçek şu ki, toString(), clone(), equals() yöntemleri gibi Java (yani standart benzeri) C++ operatörünün aşırı yüklenmesi, C++ 'ın o kadar fazla parçasıdır ki, orijinal C operatörleri kadar doğal olur veya daha önce bahsedilen Java yöntemleri.

Şablon programlama ile birleştirildiğinde, operatörün aşırı yüklenmesi iyi bilinen bir tasarım deseni haline gelir. Aslında, STL'de aşırı operatörleri kullanmadan ve kendi sınıfınız için aşırı operatörleri kullanmadan çok ileri gidemezsiniz.

... ama kötüye kullanılmamalıdır

Operatör aşırı yüklenmesi, operatörün anlamına saygı göstermeye çalışmalıdır. + işlecinde çıkarma yapmayın ("add işlevinde çıkarma" veya "clone yönteminde geri dönüş" ifadesinde olduğu gibi).

Oyuncularda aşırı yüklenme çok tehlikeli olabilir çünkü belirsizliklere yol açabilir. Bu nedenle, iyi tanımlanmış durumlar için gerçekten ayrılmaları gerekir. && ve ||, yerel operatörlerin && ve ||'nun zevk aldığı kısa devre değerlendirmesini kaybedeceğinizden, gerçekten ne yaptığınızı bilmediğiniz sürece onları aşırı yüklemeyin.

Öyleyse ... Tamam ... O zaman neden Java'da mümkün değil?

Çünkü James Gosling öyle dedi:

Ben operatör olarak aşırı yükleme aşırı kaldı oldukça kişisel seçim Çünkü çok fazla insanın C++ 'da suistimal ettiğini gördüm.

James Gosling. Kaynak: http: //www.gotw.ca/publications/c_family_interview.htm

Lütfen Gosling'in yukarıdaki metnini Stroustrup'unkiyle karşılaştır:

Birçok C++ tasarım kararının kökleri, insanları bir şeyleri belirli bir şekilde yapmaya zorlamadan hoşlanmamdır […] Genelde, kişisel olarak hoşlanmadığım bir özelliğin yasaklanmasına özendirildim, çünkü yapmaktan çekinmiştim. Başkaları hakkındaki görüşlerimi zorlama hakkım olduğunu düşünmedim.

Bjarne Stroustrup. Kaynak: C++ 'ın Tasarımı ve Evrimi (1.3 Genel Arkaplan)

Operatör aşırı yüklenmesi Java’ya fayda sağlar mı?

Bazı nesneler operatörün aşırı yüklenmesinden büyük ölçüde faydalanacaktır (BigDecimal, karmaşık sayılar, matrisler, kaplar, yineleyiciler, karşılaştırıcılar, ayrıştırıcılar vb. Gibi somut veya sayısal türler).

C++ 'da, Stroustrup'un alçakgönüllülüğü nedeniyle bu avantajdan yararlanabilirsiniz. Java’da, Gosling’ler yüzünden ... kişisel seçim.

Java'ya eklenebilir mi?

Java 'da şimdi operatörün aşırı yüklenmemesinin sebepleri, bir iç politika, özelliğe alerji, geliştiricilere güvensizlik (bildiğiniz gibi, taciz edenler gibi görünüyor) Java takımlar ...), önceki JVM'lerle uyumluluk, doğru şartname yazma zamanı vb.

Bu yüzden nefesini bu özelliği bekletme ...

Ama C # ile yapıyorlar !!!

Evet...

Bu, iki dil arasındaki tek fark olmaktan uzak olsa da, bu beni hiç eğlendirmiyor.

Görünüşe göre, C # ile, millet "her ilkel bir struct, ve bir struct Object'ten kaynaklanır", ilk denemede doğru anladım.

Ve bunu diğer dillerde !!!

Kullanılan tanımlanmış operatör aşırı yüklenmesine karşı tüm FUD değerlerine rağmen, aşağıdaki diller desteklemektedir: Scala , Dart , Python , F # , C # , D , ALGOL 68 , Smalltalk , Groovy , Perl 6 , C++, Ruby , Haskell , MATLAB , Eiffel , Lua , Clojure , Fortran 90 , Swift , Ada , Delphi 2005 ...

Pek çok dil, pek çok farklı (ve bazen de birbiriyle çelişen) felsefesi var ve yine de hepsi bu noktada aynı fikirdeler.

Düşünce için yemek ...

760
paercebal

James Gosling, Java'yı şu şekilde tasarlamaya çalıştı:

“Bir daireden diğerine taşındığınızda taşınmayla ilgili bu prensip var. İlginç bir deney, dairenizi toplayıp kutulara koymak, daha sonra bir sonraki daireye geçmek ve ihtiyacınız olana kadar hiçbir şeyi açmak değil.” ilk yemeğinizi hazırlıyorsunuz ve bir kutunun dışına bir şey çıkarıyorsunuz. Sonra bir ay ya da öylesine kullandınız ki, yaşamınızda gerçekte neye ihtiyaç duyduğunuzu bulmak için kullandınız ve sonra gerisini alıyorsunuz. şeyler - ne kadar sevdiğini ya da ne kadar havalı olduğunu unut - ve sadece fırlatıp at, bu hayatını kolaylaştıracak şaşırtıcı ve bu prensibi her türlü tasarım konusunda kullanabiliyorsun: "Havalı ya da sadece ilginç oldukları için."

Alıntı içeriğinin bölümünü okuyabilirsiniz

Temel olarak operatör aşırı yüklemesi, bir tür nokta, para birimi veya karmaşık sayı modelleyen bir sınıf için mükemmeldir. Fakat bundan sonra hızlı bir şekilde örneklerin tükenmesine başlarsın.

Diğer bir faktör ise, C++ 'daki özelliğin' && ',' || ', cast operatörleri ve elbette' new 'gibi operatörleri aşırı yüklemesiyle kötüye kullanılmasıydı. Bunun değer ve istisnalar ile geçişle birleştirilmesinden kaynaklanan karmaşıklık, İstisnai C++ kitabında ele alınmıştır.

39
Garth Gilmour

Boost.Units'e göz atın: bağlantı metni

Operatör aşırı yüklemesi ile sıfır yükü Boyutlu analiz sağlar. Bu ne kadar netleşebilir?

quantity<force>     F = 2.0*newton;
quantity<length>    dx = 2.0*meter;
quantity<energy>    E = F * dx;
std::cout << "Energy = " << E << endl;

aslında doğru olan "Enerji = 4 J" değerini verirdi.

20
user15793

Java tasarımcıları, operatörün aşırı yüklenmesinin değerinden daha fazla sorun olduğuna karar verdi. Bu kadar basit.

Her nesne değişkeninin aslında referans olduğu bir dilde, operatörün aşırı yüklenmesi, oldukça mantıksız olma tehlikesini de beraberinde getirir - en azından bir C++ programcısına. Durumu C # '= = operatör aşırı yüklenmesi ve Object.Equals ve Object.ReferenceEquals (veya ne olursa olsun) ile karşılaştırın.

11
Sebastian Redl

Groovy , operatörün aşırı yüklenmesine sahip ve JVM'de çalışıyor. Performansı sakıncası yoksa (ki her gün daha küçük olur). Metot adlarına göre otomatiktir. örneğin, '+' 'plus (argüman)' yöntemini çağırır.

8
noah

Bunun, geliştiricileri isimlerini niyetlerini açıkça ifade eden işlevler oluşturmaya zorlamak için bilinçli bir tasarım seçimi olabileceğini düşünüyorum. C++ 'da geliştiriciler, operatörleri, verilen operatörün genel kabul görmüş doğası ile genellikle ilişkili olmayan fonksiyonelliğe aşırı yükleyerek operatör tanımına bakmadan ne tür bir kodun yapılacağını belirlemeyi neredeyse imkansız hale getirir.

6
user14128

Eh, operatörün aşırı yüklenmesi ile gerçekten kendinizi ayağınızdan vurabilirsiniz. İşaretçilerde olduğu gibi, insanlar da onlarla aptalca hatalar yapar ve bu yüzden makası elinden almaya karar verdi.

En azından bence sebebi bu .. .. zaten senin yanındayım. :)

5
Sarien

Teknik olarak, her programlama dilinde, farklı sayı tipleriyle başa çıkabilen operatör aşırı yüklemesi vardır; tam sayı ve gerçek sayılar. Açıklama: Aşırı yükleme terimi, bir fonksiyon için sadece birkaç uygulamanın olduğu anlamına gelir. Çoğu programlama dilinde, operatör + için bir tamsayı, bir gerçek için diğeri operatör aşırı yüklemesi olarak adlandırılan farklı uygulamalar sağlanmıştır.

Şimdi, birçok kişi Java'nın operatör için + birlikte dizeler eklemek için operatör aşırı yüklemesine sahip olmasının garip olduğunu ve matematiksel bir bakış açısıyla bunun gerçekten garip olacağını, ancak bir programlama dilinin geliştiricisinin bakış açısından görüldüğü gibi, yerleşik operatör aşırı yüklemesi eklerken yanlış bir şey olmadığını operatör + için diğer sınıflar için Dize. Bununla birlikte, çoğu kişi String için + için yerleşik aşırı yükleme ekledikten sonra, geliştiriciye de bu işlevi sağlamanın iyi bir fikir olduğunu kabul eder.

Tamamen operatörün aşırı yüklendiği yanlışlığına tamamen katılmıyorum, çünkü geliştirici karar verecek. Bu düşünmek için saf ve oldukça dürüst olmak gerekirse, yaşlanıyor.

Java 8'de operatör aşırı yüklemesi eklemek için +1.

4
Olai

Operatör aşırı yüklenmesinin operatörün işlem mantığına uymadığı mantıksal hatalara yol açtığını söylemek, hiçbir şey söylememek gibi bir şey. Eğer fonksiyon adı işlem mantığı için uygun değilse, aynı tip hata oluşacaktır - peki çözüm nedir: fonksiyon kullanım kabiliyetini bırakın !? Bu komik bir cevaptır - "İşlem mantığı için uygun değil", her parametre adı, her sınıf, işlev veya mantıksal olarak uygun olmayan herhangi bir şey . güvensiz - hey, hayır, her ikisi de kullanmanız gerektiğini söylüyor. Hadi C # alalım. İşaretçileri bıraktılar ama hey - 'güvenli olmayan kod' ifadesi var - istediğin gibi program kendi sorumluluğunda.

4
Kvant

Bazı insanlar, operatörün Java’da aşırı yüklenmesinin karışıklığa yol açacağını söylüyor. Bu insanlar BigDecimal kullanarak yüzde değerinde bir finansal değer artırma gibi bazı temel matematik işlemleri yapan Java kodlarına bakmak için hiç durdular mı? .... böyle bir alıştırmanın ayrıntılandırılması, kendi saplantılarını gösterme haline gelir. İronik olarak, operatöre Java'ya aşırı yükleme eklenmesi, bu matematik kodunu zarif ve basit (daha az karıştırılmış) yapan kendi Para Birim sınıfımızı oluşturmamıza izin verir.

3
Volksman

Java'yı uygulama dili olarak kabul ettikten sonra a, b ve c'nin tümü, null değerinin başlangıç ​​değerleriyle birlikte Complex türüne referanslar olacaktır. Ayrıca, Kompleksin belirtilen BigInteger ve benzeri değişmez BigDecimal olarak değişmez olduğunu varsayarak, b ve c'nin eklenmesinden döndürülen Kompleks'e başvuru atarken aşağıdakileri kastediyoruz. ve bu referansı a ile karşılaştırmamak.

Değil:

Complex a, b, c; a = b + c;

much şunlardan daha basit:

Complex a, b, c; a = b.add(c);
2

Bazen operatörün aşırı yüklenmesi, arkadaş sınıfları ve çoklu mirası olması iyi olurdu.

Ancak hala bunun iyi bir karar olduğunu düşünüyorum. Eğer Java'da operatörün aşırı yüklenmesi olmuş olsaydı, kaynak koduna bakmadan operatör anlamlarından asla emin olamayız. Şu anda bu gerekli değil. Ve operatör aşırı yüklemesi yerine yöntem kullanma örneğinizin de oldukça okunaklı olduğunu düşünüyorum. İşleri daha net hale getirmek istiyorsanız, tüylü ifadelerin üstüne her zaman bir yorum ekleyebilirsiniz.

// a = b + c
Complex a, b, c; a = b.add(c);
1
user14070

Java Operatörü Aşırı Yüklemesinin Yerli Desteğine Alternatifleri

Java'da operatörün aşırı yüklenmesi olmadığından, bakabileceğiniz bazı alternatifler şunlardır:

  1. Başka bir dil kullan. Her ikisi de Groovy ve Scala / operatör aşırı yüklemesi var ve Java'ya dayanıyor.
  2. Kullanıcının Java'da aşırı yüklenmesini sağlayan bir eklenti Java-oo kullanın. Platformdan bağımsız olmadığını unutmayın. Ayrıca, birçok sorunu var ve en son Java sürümleriyle uyumlu değil (ör. Java 10). ( Orijinal StackOverflow Kaynağı )
  3. JNI , Java Yerel Arabirimi veya alternatifleri kullanın. Bu, Java'da kullanım için C veya C++ (belki başkaları?) Yöntemleri yazmanıza izin verir. Tabii ki bu platformdan bağımsız DEĞİLDİR.

Herhangi biri başkalarının farkındaysa, lütfen yorum yapın, ben de bu listeye ekleyeceğim.

0
gagarwa

Bu ona izin vermemek için iyi bir neden değil, pratik bir:

İnsanlar her zaman sorumlu bir şekilde kullanmazlar. Bu örneğe Python kütüphanesi scapy'sinden bakın:

>>> IP()
<IP |>
>>> IP()/TCP()
<IP frag=0 proto=TCP |<TCP |>>
>>> Ether()/IP()/TCP()
<Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>>
>>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
<IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>>
>>> Ether()/IP()/IP()/UDP()
<Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>>
>>> IP(proto=55)/TCP()
<IP frag=0 proto=55 |<TCP |>>

İşte açıklama:

/ Operatörü, iki .__ arasında bir kompozisyon operatörü olarak kullanılmıştır. katmanlar. Bunu yaparken, alt tabaka bir veya daha fazla karakterine sahip olabilir. varsayılan alanlar, üst katmana göre aşırı yüklenmiş alanlar. (Siz hala İstediğiniz değeri verebilirsiniz). Bir dize ham katman olarak kullanılabilir.

0
Sarien