java - منصة - لغة الجافا pdf




ما الغرض من المنشئات العامة التي تخدم في جافا؟ (4)

كما يعلم الجميع ، يمكنك الحصول على فئة عامة في Java باستخدام وسيطات الكتابة:

class Foo<T> {
    T tee;
    Foo(T tee) {
        this.tee = tee;
    }
}

لكن يمكنك أيضًا إنشاء مُنشئات عامة ، مما يعني أن المُنشئات يتلقون بشكل صريح وسائط نوعهم العامة ، على سبيل المثال:

class Bar {
    <U> Bar(U you) {
        // Why!?
    }
}

أنا أصارع لفهم حالة الاستخدام. ماذا تسمح لي هذه الميزة؟


ماذا تسمح لي هذه الميزة؟

هناك ثلاثة أشياء على الأقل تتيح لك القيام بذلك والتي لا يمكنك القيام بها بطريقة أخرى:

  1. التعبير عن العلاقات بين أنواع الوسائط ، على سبيل المثال:

    class Bar {
        <T> Bar(T object, Class<T> type) {
            // 'type' must represent a class to which 'object' is assignable,
            // albeit not necessarily 'object''s exact class.
            // ...
        }
    }
  2. <سحب>

  3. كما لاحظLino أولاً ، فإنه يتيح لك التعبير عن أن الوسائط يجب أن تكون متوافقة مع مجموعة من نوعين أو أكثر من الأنواع غير المرتبطة (والتي يمكن أن تكون منطقية عندما تكون جميعها أنواع واجهة واحدة على الأكثر). انظر إجابة لينو للحصول على مثال.


في الواقع ، هذا المنشئ

class Bar {
    <U> Bar(U you) {
        // Why!?
    }
}

هو تماما مثل طريقة عامة . سيكون من المنطقي أكثر بكثير إذا كان لديك وسيطات مُنشئ متعددة مثل هذه:

class Bar {
    <U> Bar(U you, List<U> me) {
        // Why!?
    }
} 

ثم يمكنك فرض القيد ، أن لديهم نفس الوقت مع المترجم. دون أن تجعل U عامًا للصف بأكمله.


من الواضح في المثال الذي قدمته أن U لا يلعب أي دور في مُنشئ الفصل ، لأنه يصبح فعليًا Object في وقت التشغيل:

class Bar {
    <U> Bar(U you) {
        // Why!?
    }
}

ولكن دعنا نقول أنني أردت منشئي قبول الأنواع التي تمدد فئة أو واجهة أخرى فقط ، كما هو موضح أدناه:

class Foo<T extends Baz> {
    <U extends Bar> Foo(U u) {
        // I must be a Bar!
    }
}

لاحظ أن الفئة لديها بالفعل نوع عام مختلف قيد الاستخدام ؛ يتيح لك هذا استخدام نوع عام منفصل غير متعلق بتعريف الفئة.

منحت ، لم أستخدم شيئًا كهذا مطلقًا ، ولم أره أبدًا قيد الاستخدام ، لكن هذا ممكن!


نظرًا لأن هذا النوع العام غير المنضم يمحو إلى Object ، فسيكون هو نفسه تمرير Object في مُنشئك:

public class Foo {
    Object o;

    public Foo(Object o) {
        this.o = o;
    }
}

... ولكن مثل تمرير Object فارغ ، إلا إذا كنت تفعل شيئًا ذكيًا ، فهذا ليس له قيمة عملية تذكر.

ترى فوائد وتربح إذا مررت بالأدوية المربوطة بدلاً من ذلك ، مما يعني أنه يمكنك بالفعل الحصول على ضمانات حول النوع الذي تهتم به.

public class Foo<T extends Collection<?>> {
    T collection;
    public Foo(T collection) {
        this.collection = collection;
    }
}

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





constructor