سؤال

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

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

المحلول

وولغة جافا لتشبه وظيفة مؤشر الأداء الوظيفي هو فئة مجهولة تنفيذ واجهة، منها مثلا.

Collections.sort(list, new Comparator<MyClass>(){
    public int compare(MyClass a, MyClass b)
    {
        // compare objects
    }
});

<القوي> تحديث: كما هو ضروري أعلاه في إصدارات جاوة قبل جافا 8. الآن لدينا بدائل أجمل بكثير، وهي lambdas:

list.sort((a, b) -> a.isGreaterThan(b));

ووالمراجع الأسلوب:

list.sort(MyClass::isGreaterThan);

نصائح أخرى

ويمكنك substitue مؤشر دالة مع واجهة. دعونا نقول كنت تريد أن تعمل من خلال مجموعة وتفعل شيئا مع كل عنصر.

public interface IFunction {
  public void execute(Object o);
}

وهذه هي واجهة نحن يمكن أن تمر على بعض يقول CollectionUtils2.doFunc (مجموعة ج، IFunction و).

public static void doFunc(Collection c, IFunction f) {
   for (Object o : c) {
      f.execute(o);
   }
}

وكمثال على ذلك نقول لدينا مجموعة من الأرقام وكنت أود أن أضيف 1 إلى كل عنصر.

CollectionUtils2.doFunc(List numbers, new IFunction() {
    public void execute(Object o) {
       Integer anInt = (Integer) o;
       anInt++;
    }
});

ويمكنك استخدام انعكاس للقيام بذلك.

وتمرير كمعلمة الكائن واسم الأسلوب (كسلسلة) ثم استدعاء الأسلوب. على سبيل المثال:

Object methodCaller(Object theObject, String methodName) {
   return theObject.getClass().getMethod(methodName).invoke(theObject);
   // Catch the exceptions
}

وثم استخدامه كما في:

String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");

وبطبيعة الحال، تحقق من كل الاستثناءات وإضافة يلقي الحاجة.

لا، وظائف ليست كائنات من الدرجة الأولى في جافا. يمكنك أن تفعل الشيء نفسه عن طريق تنفيذ طبقة معالج - هذه هي الطريقة التي يتم تنفيذ الاستدعاء في سوينغ الخ

ولكن هناك مقترحات لإغلاق (الاسم الرسمي لما كنت تتحدث عن) في الإصدارات المستقبلية من جافا - <وأ href = "http://www.javaworld.com/javaworld/jw-06-2008/ JW-06-closures.html "يختلط =" noreferrer "> و JavaWorld ديه مادة مثيرة للاهتمام.

وهذا يعيد إلى الأذهان href="http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html" تنفيذ ستيف ييغج في المملكة الاسماء . وتنص أساسا أن جافا يحتاج كائن لكل عمل، وبالتالي لم يكن لديك الكيانات "الفعل فقط" مثل مؤشرات الدالة.

لتحقيق وظائف مماثلة هل يمكن استخدام الطبقات الداخلية مجهولة.

إذا كنت لتحديد Foo اجهة:

interface Foo {
    Object myFunc(Object arg);
}

وإنشاء bar الطريقة التي سوف تحصل على "مؤشر الدالة 'كحجة:

public void bar(Foo foo) {
    // .....
    Object object = foo.myFunc(argValue);
    // .....
}

وأخيرا استدعاء الأسلوب كما يلي:

bar(new Foo() {
    public Object myFunc(Object arg) {
        // Function code.
    }
}
lambdas

لقد قدم Java8 و . إذا كان الأمر كذلك وظيفة مباريات و اجهة ظيفية ( يمكنك إنشاء الخاصة بك) يمكنك استخدام مرجع الأسلوب في هذه القضية.

يوفر

وجافا مجموعة من شيوعا واجهات وظيفية . في حين يمكن القيام بما يلي:

public class Test {
   public void test1(Integer i) {}
   public void test2(Integer i) {}
   public void consumer(Consumer<Integer> a) {
     a.accept(10);
   }
   public void provideConsumer() {
     consumer(this::test1);   // method reference
     consumer(x -> test2(x)); // lambda
   }
}

وليس هناك شيء من هذا القبيل في جاوة. سوف تحتاج إلى التفاف وظيفة الخاص بك إلى بعض وجوه وتمرير إشارة إلى هذا الكائن من أجل تمرير الإشارة إلى الطريقة على هذا الكائن.

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

مثال:

class MyComponent extends JPanel {
    private JButton button;
    public MyComponent() {
        button = new JButton("click me");
        button.addActionListener(buttonAction);
        add(button);
    }

    private ActionListener buttonAction = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // handle the event...
            // note how the handler instance can access 
            // members of the surrounding class
            button.setText("you clicked me");
        }
    }
}

لقد قمت بتنفيذ دعم رد الاتصال/التفويض في Java باستخدام الانعكاس.التفاصيل ومصدر العمل هي متاح على موقع الويب الخاص بي.

كيف تعمل

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

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

لكي تكون صفيف المعاملات آمنًا، يجب أن تكون صفيف المعلمات موجودًا بشكل فريد لكل استدعاء لأسلوب API، ومن أجل الكفاءة، يجب استخدام نفس المصفوفة لكل استدعاء لاستدعاء رد الاتصال؛كنت بحاجة إلى كائن ثانٍ سيكون إنشاءه رخيصًا من أجل ربط رد الاتصال بمصفوفة معلمات للاستدعاء.ولكن، في بعض السيناريوهات، قد يكون لدى المستدعي بالفعل مصفوفة معلمات لأسباب أخرى.لهذين السببين، لا ينتمي صفيف المعلمة إلى كائن رد الاتصال.كما أن اختيار الاستدعاء (تمرير المعلمات كمصفوفة أو ككائنات فردية) ينتمي إلى أيدي واجهة برمجة التطبيقات باستخدام رد الاتصال مما يمكّنها من استخدام أي استدعاء يناسب أعمالها الداخلية.

تعد فئة WithParms المتداخلة اختيارية وتخدم غرضين، فهي تحتوي على مصفوفة كائن المعلمة اللازمة لاستدعاءات رد الاتصال، وتوفر 10 طرق استدعاء () مثقلة (مع من 1 إلى 10 معلمات) والتي تقوم بتحميل مصفوفة المعلمات ثم استدعاء هدف رد الاتصال.

والتحقق من إغلاق الكيفية التي تم تنفيذها في المكتبة lambdaj. لديهم في الواقع سلوك مشابه جدا لC # المندوبين:

http://code.google.com/p/lambdaj/wiki/Closures

وبالنسبة لمعظم الناس هنا أنا جديدة على جافا ولكن بما أنني لم أر اقتراح مماثل لدي بديل آخر لاقتراح. لست متأكدا إذا كان لها ممارسة جيدة أم لا، أو حتى اقترح قبل وأنا فقط لم تحصل عليه. أنا فقط أحب ذلك منذ أعتقد النفس وصفي.

 /*Just to merge functions in a common name*/
 public class CustomFunction{ 
 public CustomFunction(){}
 }

 /*Actual functions*/
 public class Function1 extends CustomFunction{
 public Function1(){}
 public void execute(){...something here...}
 }

 public class Function2 extends CustomFunction{
 public Function2(){}
 public void execute(){...something here...}
 }

 .....
 /*in Main class*/
 CustomFunction functionpointer = null;

وبعد ذلك اعتمادا على التطبيق، تعيين

 functionpointer = new Function1();
 functionpointer = new Function2();

وغيرها.

ووالدعوة التي كتبها

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