سؤال

من C++ إلى Java، السؤال الواضح الذي لم تتم الإجابة عليه هو لماذا لم تتضمن Java التحميل الزائد للمشغل؟

ليس كذلك Complex a, b, c; a = b + c; أبسط بكثير من Complex a, b, c; a = b.add(c);?

هل هناك سبب معروف لذلك، حجج صحيحة ل لا السماح الزائد المشغل؟هل السبب تعسفي أم ضائع مع الزمن؟

هل كانت مفيدة؟

المحلول

على افتراض أنك تريد الكتابة فوق القيمة السابقة للكائن المشار إليه بواسطة a, ، فيجب استدعاء وظيفة العضو.

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

في لغة C++، يخبر هذا التعبير المترجم بإنشاء ثلاثة (3) كائنات على المكدس، وإجراء عملية الإضافة، و ينسخ القيمة الناتجة من الكائن المؤقت إلى الكائن الموجود a.

ومع ذلك، في جافا، operator= لا يقوم بنسخ القيمة لأنواع المراجع، ويمكن للمستخدمين إنشاء أنواع مرجعية جديدة فقط، وليس أنواع القيم.لذلك بالنسبة للنوع المحدد من قبل المستخدم المسمى Complex, التعيين يعني نسخ مرجع إلى قيمة موجودة.

فكر بدلاً من ذلك:

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

في لغة C++، يؤدي هذا إلى نسخ القيمة، وبالتالي فإن المقارنة ستؤدي إلى عدم المساواة.في جافا، operator= ينفذ نسخة مرجعية، لذلك a و b تشير الآن إلى نفس القيمة.ونتيجة لذلك، ستنتج المقارنة "مساويًا"، لأن الكائن سيقارن مساويًا لنفسه.

يؤدي الاختلاف بين النسخ والمراجع إلى زيادة الارتباك الناتج عن التحميل الزائد للمشغل.كما ذكرSebastian، يتعين على كل من Java وC# التعامل مع القيمة والمساواة المرجعية بشكل منفصل - operator+ من المحتمل أن يتعامل مع القيم والأشياء، ولكن operator= تم تنفيذه بالفعل للتعامل مع المراجع.

في لغة C++، يجب أن تتعامل فقط مع نوع واحد من المقارنة في كل مرة، لذلك يمكن أن يكون الأمر أقل إرباكًا.على سبيل المثال، على Complex, operator= و operator== كلاهما يعمل على القيم - نسخ القيم ومقارنة القيم على التوالي.

نصائح أخرى

هناك الكثير من المشاركات التي تشكو من التحميل الزائد على المشغل.

شعرت أنه يتعين علي توضيح مفاهيم "التحميل الزائد على المشغل"، وتقديم وجهة نظر بديلة حول هذا المفهوم.

رمز غامض؟

هذه الحجة مغالطة.

التشويش ممكن بكل اللغات..

من السهل تشويش التعليمات البرمجية في C أو Java من خلال الوظائف/الطرق كما هو الحال في C++ من خلال التحميل الزائد للمشغل:

// 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 القياسية

للحصول على مثال آخر، دعونا نرى Cloneable واجهه المستخدم في جافا:

من المفترض أن تقوم باستنساخ الكائن الذي يقوم بتنفيذ هذه الواجهة.ولكن هل يمكن أن تكذب.وإنشاء كائن مختلف.في الواقع، هذه الواجهة ضعيفة جدًا بحيث يمكنك إرجاع نوع آخر من الكائنات تمامًا، فقط من أجل المتعة:

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

كما Cloneable يمكن إساءة استخدام/تشويش الواجهة، هل يجب حظرها على نفس الأسس التي من المفترض أن يكون عليها التحميل الزائد لمشغل C++؟

يمكننا أن نثقل كاهلنا toString() طريقة أ MyComplexNumber class لجعله يعيد الساعة المتشددة من اليوم.ينبغي لل toString() سيتم حظر الحمولة الزائدة أيضا؟يمكننا التخريب MyComplexNumber.equals لجعلها ترجع قيمة عشوائية، قم بتعديل المعاملات ...إلخ.إلخ.إلخ..

في Java، كما هو الحال في C++، أو أي لغة أخرى، يجب على المبرمج احترام الحد الأدنى من الدلالات عند كتابة التعليمات البرمجية.وهذا يعني تنفيذ أ add الوظيفة التي تضيف، و Cloneable طريقة التنفيذ التي استنساخ، و ++ عامل من الزيادات.

ما هو التشويش على أي حال؟

الآن بعد أن علمنا أنه يمكن تخريب التعليمات البرمجية حتى من خلال أساليب Java الأصلية، يمكننا أن نسأل أنفسنا عن الاستخدام الحقيقي للتحميل الزائد للمشغل في C++؟

تدوين واضح وطبيعي:الأساليب مقابلالتحميل الزائد للمشغل؟

سنقارن أدناه، في حالات مختلفة، الكود "نفسه" في Java وC++، للحصول على فكرة عن نوع نمط الترميز الأكثر وضوحًا.

المقارنات الطبيعية:

// 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 ;

يرجى ملاحظة أن A وB يمكن أن يكونا من أي نوع في C++، طالما تم توفير التحميل الزائد للمشغل.في Java، عندما لا يكون A وB أساسيين، يمكن أن تصبح التعليمات البرمجية مربكة للغاية، حتى بالنسبة للكائنات الشبيهة بالبدائية (BigInteger، وما إلى ذلك)...

الوصول إلى المصفوفة/الحاوية الطبيعية والاشتراك:

// 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، نرى أنه لكي تفعل كل حاوية نفس الشيء (الوصول إلى محتواها من خلال فهرس أو معرف)، لدينا طريقة مختلفة للقيام بذلك، وهو أمر محير.

في لغة C++، تستخدم كل حاوية نفس الطريقة للوصول إلى محتواها، وذلك بفضل التحميل الزائد للمشغل.

التلاعب بالأنواع الطبيعية المتقدمة

تستخدم الأمثلة أدناه أ Matrix كائن، تم العثور عليه باستخدام الروابط الأولى الموجودة على Google لـ "كائن مصفوفة جافا" و "كائن مصفوفة ج ++":

// 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

وهذا لا يقتصر على المصفوفات.ال BigInteger و BigDecimal تعاني فئات Java من نفس الإسهاب المربك، في حين أن مرادفاتها في C++ واضحة مثل الأنواع المضمنة.

التكرارات الطبيعية:

// 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

العوامل الطبيعية:

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

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

تسلسل النص:

// 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") ;

حسنا، في جافا يمكنك استخدامها MyString = "Hello " + 25 + " World" ; أيضاً...لكن انتظر ثانية:هذا هو التحميل الزائد للمشغل، أليس كذلك؟أليس هذا خيانة؟؟؟

:-د

الكود العام؟

يجب أن تكون نفس معاملات تعديل التعليمات البرمجية العامة قابلة للاستخدام لكل من العناصر المضمنة/الأوليات (التي ليس لها واجهات في Java)، والكائنات القياسية (التي لا يمكن أن تحتوي على الواجهة الصحيحة)، والكائنات المعرفة من قبل المستخدم.

على سبيل المثال، حساب متوسط ​​قيمة قيمتين من الأنواع العشوائية:

// 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.

مناقشة التحميل الزائد للمشغل

الآن بعد أن رأينا مقارنات عادلة بين كود C++ باستخدام التحميل الزائد للمشغل، ونفس الكود في Java، يمكننا الآن مناقشة "التحميل الزائد للمشغل" كمفهوم.

كان التحميل الزائد على المشغل موجودًا منذ ما قبل أجهزة الكمبيوتر

حتى خارج علوم الكمبيوتر، هناك تحميل زائد للمشغل:على سبيل المثال، في الرياضيات، المشغلين يحبون +, -, *, ، إلخ.مثقلة.

والواقع أن دلالة +, -, *, ، إلخ.تتغير اعتمادًا على أنواع المعاملات (الأرقام، المتجهات، وظائف الموجة الكمومية، المصفوفات، إلخ).

لقد تعلم معظمنا، كجزء من دوراتنا العلمية، دلالات متعددة للعوامل، اعتمادًا على أنواع المعاملات.هل وجدناهم مربكين، هم؟

يعتمد التحميل الزائد للمشغل على معاملاته

هذا هو الجزء الأكثر أهمية في التحميل الزائد للمشغل:كما هو الحال في الرياضيات، أو في الفيزياء، تعتمد العملية على أنواع معاملاتها.

فاعرف نوع المعامل وستعرف تأثير العملية.

حتى C و Java لديهما تحميل زائد للمشغل (مشفر بشكل ثابت).

في لغة C، يتغير السلوك الحقيقي للمشغل وفقًا لمعاملاته.على سبيل المثال، جمع عددين صحيحين يختلف عن إضافة عددين مزدوجين، أو حتى عدد صحيح واحد ومضاعف واحد.يوجد أيضًا المجال الحسابي للمؤشر بالكامل (بدون التحويل، يمكنك إضافة عدد صحيح إلى المؤشر، لكن لا يمكنك إضافة مؤشرين...).

في Java، لا يوجد مؤشر حسابي، ولكن لا يزال هناك شخص ما يعثر على تسلسل سلسلة بدون + سيكون المشغل سخيفًا بما يكفي لتبرير الاستثناء في عقيدة "التحميل الزائد للمشغل أمر شرير".

إنه مجرد أنك، باعتبارك لغة C (لأسباب تاريخية) أو Java (لـ اسباب شخصية, ، انظر أدناه) المبرمج، لا يمكنك تقديم برنامجك الخاص.

في C++، التحميل الزائد للمشغل ليس اختياريًا ...

في C++، التحميل الزائد للمشغل للأنواع المضمنة غير ممكن (وهذا أمر جيد)، ولكن تعريف المستخدم أنواع يمكن أن يكون تعريف المستخدم الزائد المشغل.

كما ذكرنا سابقًا، في لغة C++، وعلى العكس من Java، لا تعتبر أنواع المستخدمين مواطنين من الدرجة الثانية في اللغة، عند مقارنتها بالأنواع المضمنة.لذلك، إذا كانت الأنواع المضمنة تحتوي على عوامل تشغيل، فيجب أن تكون أنواع المستخدمين قادرة على الحصول عليها أيضًا.

الحقيقة هي أنه مثل toString(), clone(), equals() الأساليب مخصصة لـ Java (أي.شبه قياسي)، يعد التحميل الزائد لمشغل C++ جزءًا كبيرًا من C++ بحيث يصبح طبيعيًا مثل عوامل تشغيل C الأصلية، أو طرق Java المذكورة سابقًا.

بالاشتراك مع برمجة القالب، يصبح التحميل الزائد للمشغل نمطًا تصميميًا معروفًا.في الواقع، لا يمكنك الذهاب بعيدًا في STL دون استخدام عوامل التحميل الزائد، وعوامل التحميل الزائد لفصلك الخاص.

...ولكن لا ينبغي إساءة استخدامه

يجب أن يسعى التحميل الزائد للمشغل إلى احترام دلالات المشغل.لا تطرح في أ + عامل التشغيل (كما في "لا تطرح في add وظيفة"، أو" إرجاع حماقة في ملف clone طريقة").

يمكن أن يكون التحميل الزائد للطاقم خطيرًا جدًا لأنه قد يؤدي إلى الغموض.لذلك يجب أن يتم حجزها لحالات محددة جيدًا.أما بالنسبة لل && و ||, ، لا تفرط في تحميلها أبدًا إلا إذا كنت تعرف حقًا ما تفعله، حيث ستفقد تقييم الدائرة القصيرة الذي يقوم به المشغلون الأصليون && و || يتمتع.

لذا...نعم...إذن لماذا هذا غير ممكن في جافا؟

لأن جيمس جوسلينج قال ذلك:

لقد تركت التحميل الزائد للمشغل باعتباره اختيار شخصي إلى حد ما لأنني رأيت الكثير من الأشخاص يسيئون استخدامه في لغة C++.

جيمس جوسلينج.مصدر: http://www.gotw.ca/publications/c_family_interview.htm

يرجى مقارنة نص جوسلينج أعلاه مع نص ستروستروب أدناه:

تعود جذور العديد من قرارات تصميم لغة C++ إلى كرهي لإجبار الأشخاص على القيام بأشياء بطريقة معينة [...] في كثير من الأحيان، كنت أميل إلى حظر ميزة لم تعجبني شخصيًا، وامتنعت عن القيام بذلك بسبب لم أكن أعتقد أن لدي الحق في فرض آرائي على الآخرين.

بيارن ستروستروب.مصدر:تصميم وتطور لغة C++ (1.3 الخلفية العامة)

هل يمكن أن يفيد التحميل الزائد للمشغل جافا؟

قد تستفيد بعض الكائنات بشكل كبير من التحميل الزائد للمشغل (الأنواع الملموسة أو العددية، مثل BigDecimal، والأرقام المركبة، والمصفوفات، والحاويات، والمكررات، والمقارنات، والموزعين، وما إلى ذلك).

في لغة C++، يمكنك الاستفادة من هذه الميزة بسبب تواضع ستروستروب.في جافا، أنت ببساطة في وضع سيء بسبب جوسلينج اختيار شخصي.

هل يمكن إضافتها إلى جافا؟

يمكن أن تكون أسباب عدم إضافة التحميل الزائد للمشغل الآن في Java مزيجًا من السياسات الداخلية، والحساسية تجاه الميزة، وعدم الثقة في المطورين (كما تعلمون، المخربون الذين يبدو أنهم يطاردون فرق Java...)، والتوافق مع JVMs السابقة، الوقت لكتابة المواصفات الصحيحة، الخ.

لذلك لا تحبس أنفاسك في انتظار هذه الميزة...

لكنهم يفعلون ذلك في C#!!!

نعم...

في حين أن هذا ليس هو الفرق الوحيد بين اللغتين، إلا أن هذا لا يفشل أبدًا في إمتاعتي.

على ما يبدو، فإن الأشخاص C#، مع "كل بدائي هو أ struct, ، و أ struct مشتق من الكائن", ، لقد نجحت في المحاولة الأولى.

ويفعلون ذلك في لغات اخرى!!!

على الرغم من كل FUD ضد التحميل الزائد المحدد للمشغل، فإن اللغات التالية تدعمه: سكالا, سهم, بايثون, F#, ج#, د, الغول 68, حديث قصير, رائع, بيرل 6, ، سي ++، روبي, هاسكل, ماتلاب, ايفل, لوا, كلوجر, فورتران 90, سويفت, آدا, دلفي 2005...

هناك العديد من اللغات، التي لديها العديد من الفلسفات المختلفة (وأحيانًا المتعارضة)، ومع ذلك تتفق جميعها على هذه النقطة.

غذاء للفكر...

شبه جيمس جوسلينج تصميم جافا بما يلي:

"هناك هذا المبدأ المتعلق بالانتقال، عندما تنتقل من شقة إلى شقة أخرى.إحدى التجارب المثيرة للاهتمام هي أن تحزم شقتك وتضع كل شيء في صناديق، ثم تنتقل إلى الشقة التالية ولا تقم بتفريغ أي شيء حتى تحتاج إليه.إذًا أنت تقوم بإعداد وجبتك الأولى، وتقوم بسحب شيء ما من الصندوق.ثم بعد شهر أو نحو ذلك، تستخدم ذلك لمعرفة ما هي الأشياء التي تحتاجها بالفعل في حياتك، ثم تأخذ بقية الأشياء - وتنسى مدى إعجابك بها أو مدى روعتها - و أنت فقط ترميها بعيدًا.إنه لأمر مدهش كيف أن هذا يبسط حياتك، ويمكنك استخدام هذا المبدأ في جميع أنواع مشكلات التصميم:لا تفعل الأشياء لمجرد أنها رائعة أو لأنها مثيرة للاهتمام."

يمكنك قراءة سياق الاقتباس هنا

يعد التحميل الزائد للمشغل أمرًا رائعًا للفئة التي تمثل نوعًا ما من النقاط أو العملات أو الأعداد المركبة.ولكن بعد ذلك تبدأ الأمثلة في النفاد بسرعة.

كان العامل الآخر هو إساءة استخدام الميزة في لغة C++ من قبل المطورين الذين قاموا بتحميل زائد على عوامل تشغيل مثل '&&'، و'||'، ومشغلي البث، وبالطبع 'new'.تمت تغطية التعقيد الناتج عن الجمع بين هذا مع قيمة التمرير والاستثناءات بشكل جيد في استثنائية C ++ كتاب.

تحقق من Boost.Units: نص الرابط

إنه يوفر تحليل الأبعاد بدون حمل من خلال التحميل الزائد للمشغل.ما مدى وضوح هذا الأمر؟

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

سيخرج في الواقع "الطاقة = 4 J" وهو صحيح.

قرر مصممو Java أن التحميل الزائد على المشغل يمثل مشكلة أكثر مما يستحق.سهل هكذا.

في لغة حيث كل متغير كائن هو في الواقع مرجع، فإن التحميل الزائد للمشغل يؤدي إلى خطر إضافي يتمثل في كونه غير منطقي تمامًا - بالنسبة لمبرمج C++ على الأقل.قارن الموقف مع التحميل الزائد للمشغل == في C# و Object.Equals و Object.ReferenceEquals (أو ما يسمى).

رائع يحتوي على تحميل زائد للمشغل، ويعمل في JVM.إذا كنت لا تمانع في تحقيق الأداء (الذي يصبح أصغر كل يوم).إنه تلقائي بناءً على أسماء الطرق.على سبيل المثال، يستدعي "+" طريقة "زائد (وسيطة)".

أعتقد أن هذا ربما كان اختيارًا واعيًا للتصميم لإجبار المطورين على إنشاء وظائف تعبر أسماؤها بوضوح عن نواياهم.في لغة C++، قد يزيد المطورون من تحميل المشغلين بوظائف لا علاقة لها غالبًا بالطبيعة المقبولة عمومًا للمشغل المحدد، مما يجعل من المستحيل تقريبًا تحديد ما يفعله جزء من التعليمات البرمجية دون النظر إلى تعريف المشغل.

حسنًا، يمكنك حقًا إطلاق النار على قدمك من خلال التحميل الزائد على المشغل.يبدو الأمر كما لو أن الأشخاص يرتكبون أخطاء غبية في استخدام المؤشرات، ولذلك تقرر أخذ المقص بعيدًا.

على الأقل أعتقد أن هذا هو السبب.أنا إلى جانبك على أي حال.:)

إن القول بأن التحميل الزائد للمشغل يؤدي إلى أخطاء منطقية من النوع الذي لا يتطابق فيه المشغل مع منطق التشغيل، يشبه عدم قول أي شيء.سيحدث نفس النوع من الخطأ إذا كان اسم الوظيفة غير مناسب لمنطق العملية - فما الحل:إسقاط القدرة على استخدام الوظيفة !؟هذه إجابة كوميدية - "غير مناسب لمنطق التشغيل"، كل اسم معلمة، كل فئة، وظيفة أو أي شيء يمكن أن يكون غير مناسب منطقيًا.أعتقد أن هذا الخيار يجب أن يكون متاحًا بلغة برمجة محترمة، وأولئك الذين يعتقدون أنه غير آمن - مرحبًا، لا يقول كلاهما أنه يتعين عليك استخدامه.لنأخذ C#.لقد أسقطوا المؤشرات ولكن مهلا - هناك عبارة "رمز غير آمن" - قم بالبرمجة كما تريد على مسؤوليتك الخاصة.

يقول بعض الناس أن التحميل الزائد للمشغل في Java قد يؤدي إلى التشويش.هل توقف هؤلاء الأشخاص يومًا عن إلقاء نظرة على بعض أكواد Java التي تقوم ببعض العمليات الحسابية الأساسية مثل زيادة القيمة المالية بنسبة مئوية باستخدام BigDecimal؟....إن الإسهاب في مثل هذا التمرين يصبح دليلاً على التشويش.ومن المفارقات أن إضافة التحميل الزائد للمشغل إلى Java سيسمح لنا بإنشاء فئة العملة الخاصة بنا والتي من شأنها أن تجعل مثل هذا الكود الرياضي أنيقًا وبسيطًا (أقل غموضًا).

من الناحية الفنية، هناك تحميل زائد للمشغل في كل لغة برمجة يمكنها التعامل مع أنواع مختلفة من الأرقام، على سبيل المثال.الأعداد الصحيحة والحقيقية.توضيح:مصطلح التحميل الزائد يعني أن هناك ببساطة عدة تطبيقات لوظيفة واحدة.في معظم لغات البرمجة يتم توفير تطبيقات مختلفة للمشغل +، وواحدة للأعداد الصحيحة، وواحدة للحقيقيات، وهذا ما يسمى التحميل الزائد للمشغل.

الآن، يجد العديد من الأشخاص أنه من الغريب أن تحتوي Java على تحميل زائد للمشغل + لإضافة سلاسل معًا، ومن وجهة نظر رياضية، سيكون هذا غريبًا بالفعل، ولكن من وجهة نظر مطور لغة البرمجة، لا حرج في إضافة التحميل الزائد للمشغل المدمج للمشغل + للفئات الأخرى على سبيل المثال.خيط.ومع ذلك، يتفق معظم الأشخاص على أنه بمجرد إضافة التحميل الزائد المدمج لـ + for String، فمن الجيد بشكل عام توفير هذه الوظيفة للمطور أيضًا.

لا أتفق تمامًا مع المغالطة القائلة بأن التحميل الزائد للمشغل يؤدي إلى تشويش التعليمات البرمجية، حيث يُترك ذلك للمطور ليقرره.من السذاجة أن نفكر في هذا الأمر، ولكي نكون صادقين تمامًا، فقد أصبح الأمر قديمًا.

+1 لإضافة التحميل الزائد للمشغل في Java 8.

بافتراض أن Java هي لغة التنفيذ، فإن a وb وc ستكون كلها مراجع للنوع Complex بقيم أولية خالية.بافتراض أيضًا أن المركب غير قابل للتغيير كما هو مذكور BigInteger وما شابه ذلك غير قابل للتغيير BigDecimal, ، أعتقد أنك تقصد ما يلي، حيث تقوم بتعيين المرجع إلى المجمع الذي تم إرجاعه من إضافة b وc، ولا تقارن هذا المرجع بـ a.

ليس :

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

كثيراً أبسط من:

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

في بعض الأحيان سيكون من الجيد أن يكون هناك تحميل زائد للمشغل وفئات الأصدقاء والميراث المتعدد.

ومع ذلك ما زلت أعتقد أنه كان قرارًا جيدًا.إذا كانت Java تحتوي على تحميل زائد للمشغل، فلن نتمكن أبدًا من التأكد من معاني المشغل دون النظر إلى كود المصدر.في الوقت الحاضر هذا ليس ضروريا.وأعتقد أن مثالك على استخدام الأساليب بدلاً من التحميل الزائد للمشغل هو أيضًا قابل للقراءة تمامًا.إذا كنت تريد أن تجعل الأمور أكثر وضوحًا، فيمكنك دائمًا إضافة تعليق فوق العبارات المزعجة.

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

وهذا ليس سببًا وجيهًا لعدم السماح بذلك ولكنه سبب عملي:

لا يستخدمه الناس دائمًا بمسؤولية.انظر إلى هذا المثال من مكتبة بايثون scapy:

>>> 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 |>>

هنا هو التوضيح:

تم استخدام / المشغل كمشغل تكوين بين طبقتين.عند القيام بذلك ، يمكن أن تحتوي الطبقة السفلية على واحدة أو أكثر من حقول الافتراضيات التي تم تحميلها وفقًا للطبقة العليا.(لا يزال بإمكانك إعطاء القيمة التي تريدها).يمكن استخدام السلسلة كطبقة خام.

بدائل الدعم الأصلي للتحميل الزائد لمشغل Java

نظرًا لأن Java لا تحتوي على تحميل زائد للمشغل، فإليك بعض البدائل التي يمكنك النظر فيها:

  1. استخدم لغة أخرى.كلاهما رائع و سكالا لديها التحميل الزائد للمشغل، وتستند إلى جافا.
  2. يستخدم java-oo, ، وهو مكون إضافي يتيح التحميل الزائد للمشغل في Java.لاحظ أنها ليست منصة مستقلة.كما أن به العديد من المشكلات، وهو غير متوافق مع أحدث إصدارات Java (أي.جافا 10).(مصدر StackOverflow الأصلي)
  3. يستخدم JNI, أو Java Native Interface أو البدائل.يتيح لك هذا كتابة طرق C أو C++ (وربما أخرى؟) لاستخدامها في Java.بالطبع هذه أيضًا ليست منصة مستقلة.

إذا كان أي شخص يعرف الآخرين، يرجى التعليق، وسأضيفه إلى هذه القائمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top