জাভা ফাংশন পয়েন্টার


148

এটি সাধারণ এবং তুচ্ছ কিছু হতে পারে তবে আমার মনে হয় এর একটি সুনির্দিষ্ট উত্তর খুঁজতে আমার সমস্যা হচ্ছে। সি # তে প্রতিনিধিদের ধারণা রয়েছে, যা সি ++ থেকে ফাংশন পয়েন্টারগুলির ধারণার সাথে দৃ .়ভাবে সম্পর্কিত। জাভাতে কি একই রকম কার্যকারিতা রয়েছে? প্রদত্ত পয়েন্টারগুলি কিছুটা অনুপস্থিত, এটি সম্পর্কে সর্বোত্তম উপায় কী? এবং পরিষ্কারভাবে বলতে গেলে, আমরা এখানে প্রথম শ্রেণির কথা বলছি।


1
আমি কেবল কৌতূহলী যে আপনি কেন এটি চান যেখানে শ্রোতা বা অন্যান্য ওওপি নির্মাণগুলি তাদের বস্তুর প্রকৃতি ধরে রেখে একই কাজটি করতে পারে। আমি বোঝাতে চাইছি ধারণার দ্বারা প্রদত্ত কার্যকারিতাটির প্রয়োজনীয়তাটি আমি বুঝতে পারি যে এটি সরল বস্তু দিয়ে অর্জন করা যেতে পারে .. যদি না হয় অবশ্যই আমি কিছু অনুপস্থিত না করি, তাই আমার এই প্রশ্নটি জিজ্ঞাসা করছি! :-)
নিউটোপিয়ান

2
জাভা 8 -এর ল্যাম্বডা এক্সপ্রেশন রয়েছে: ডকস.অরাকল.com / জাভেস / টিউটোরিয়াল / জাভা / জাভা ওউ / আপনি এইটি পরীক্ষা করে দেখতে চাইতে পারেন। কোনও ফাংশন পয়েন্টার নয়, তবে এটি আরও বেশি ব্যবহার হতে পারে।
হতাশ

6
জাভা 8 পদ্ধতির উল্লেখগুলি হ'ল আপনি যা যা জিজ্ঞাসা করছেন।
স্টিভেন

8
জাভা 8 পদ্ধতির উল্লেখগুলি হ'ল আপনি যা যা জিজ্ঞাসা করছেন। this::myMethodঅর্থহীনভাবে ল্যাম্বডা তৈরির মতো paramA, paramB -> this.myMethod(paramA, paramB)
স্টিভেন

উত্তর:


126

ফাংশন-পয়েন্টার-জাতীয় কার্যকারিতার জন্য জাভা আইডিয়ম একটি ইন্টারফেস প্রয়োগকারী একটি বেনাম শ্রেণি, যেমন

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

আপডেট: উপরের জাভা ৮ এর পূর্বে জাভা সংস্করণগুলিতে প্রয়োজনীয় Now এখন আমাদের কাছে অনেক ভাল বিকল্প রয়েছে, নাম ল্যাম্বডাস:

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

এবং পদ্ধতি রেফারেন্স:

list.sort(MyClass::isGreaterThan);

2
কৌশল নকশা প্যাটার্ন। আপনি যখন ফাংশনটি এমন কিছু অ-গ্লোবাল ডেটা ব্যবহার করতে চান যা কোনও ফাংশনের আর্গুমেন্ট হিসাবে সরবরাহ করা হয় না তখন কোনও সি বা সি ++ ফাংশন পয়েন্টারের মতো কুৎসিত নয়।
রায়েডওয়াল্ড

75
@ রেডওয়াল্ড সি ++ এ ফান্টেক্টর রয়েছে এবং সি ++ 0x এর ফান্টারের শীর্ষে ক্লোজার এবং ল্যাম্বডাস রয়েছে। এটি এমনকি রয়েছে std::bindযা ফাংশনগুলিতে পরামিতিগুলিকে আবদ্ধ করে এবং কলযোগ্য বস্তুটি দেয়। আমি এই কারণগুলিতে সি রক্ষা করতে পারি না, তবে সি ++ এর জন্য জাভা থেকে ভাল is
জিনাক করুন

21
@ জেনাক, @ রায়েডওয়াল্ড: আপনি সিতে এটি ব্যবহারকারীর ডেটাতে (যেমন: স্ট্রাক্ট) পয়েন্টার দিয়ে যাওয়ার মাধ্যমে করতে পারেন। (এবং এটি প্রতিটি নতুন স্তরের কলব্যাক ইন্ডিরিশনের সাথে আবদ্ধ করতে পারে) এটি আসলে মোটামুটি পরিষ্কার।
ব্রাইস

25
হ্যাঁ, আমি যে কোনও দিন ক্রুফটি মোড়কের ক্লাসের ওপরে সি ফাংশন পয়েন্টার নেব
বিটি

3
জাভা 8 এর জন্য আরও ভাল সিনট্যাক্স রয়েছে।
থরবজর্ন রাভন অ্যান্ডারসন

65

আপনি একটি ইন্টারফেস দিয়ে একটি ফাংশন পয়েন্টার প্রতিস্থাপন করতে পারেন। বলুন যে আপনি কোনও সংকলন চালাতে চান এবং প্রতিটি উপাদান দিয়ে কিছু করতে চান।

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

এটি এমন ইন্টারফেস যা আমরা কারও কারও কাছে বলে ফেলতে পারি কালেকশনUtils2.doFunc (কালেকশন সি, আইফঙ্কশন এফ)।

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++;
    }
});

42

এটি করতে আপনি প্রতিবিম্ব ব্যবহার করতে পারেন।

বস্তু এবং পদ্ধতির নাম (স্ট্রিং হিসাবে) হিসাবে প্যারামিটার হিসাবে পাস করুন এবং তারপরে পদ্ধতিটি চালু করুন। উদাহরণ স্বরূপ:

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

অবশ্যই, সমস্ত ব্যতিক্রম চেক করুন এবং প্রয়োজনীয় ক্যাসট যুক্ত করুন।


7
প্রতিচ্ছবি "আমি কীভাবে ধীর ডজ্বি জাভা কোড লিখব" ব্যতীত কোনও কিছুর সঠিক উত্তর নয়: ডি
জ্যাকব

5
এটি "কুরুচিপূর্ণ" এবং ধীর হতে পারে তবে আমি বিশ্বাস করি যে প্রতিচ্ছবি এমন স্টাফ করতে দেয় যা স্বীকৃত উত্তরের ইন্টারফেস-ভিত্তিক সমাধান করতে পারে না (যদি আমি ভুল না করি), একই কোডের মধ্যে একই বস্তুর বিভিন্ন পদ্ধতি কল করে name অংশ।
ইউসবিয়াস

@ জোকেটে .. আমি এই পোস্টটি দিয়ে যাচ্ছিলাম এবং আমার একটি সন্দেহ ছিল .. সুতরাং আপনার পদ্ধতির সাথে, যদি আমি পরিবর্তনশীল "দ্য ডেসক্রিপশন" অ্যাক্সেস করি তবে ফাংশনটি প্রতিটি এবং প্রতিটি সময় পরিবর্তনশীল অ্যাক্সেস করার সময় বলা হবে ??
karthik27

20

না, ফাংশন জাভাতে প্রথম শ্রেণীর অবজেক্ট নয়। আপনি হ্যান্ডলার শ্রেণি প্রয়োগ করে একই জিনিসটি করতে পারেন - দোল ইত্যাদি ক্ষেত্রে কলব্যাকগুলি এভাবে প্রয়োগ করা হয়

জাভা- ভবিষ্যতের সংস্করণগুলিতে ক্লোজারগুলির (আপনি যে বিষয়ে কথা বলছেন তার অফিশিয়াল নাম) জন্য প্রস্তাব রয়েছে - জাভাওয়ার্ল্ডের একটি আকর্ষণীয় নিবন্ধ রয়েছে।


15

এই স্টিভ Yegge মন এনেছে বিশেষ্যের রাজ্যে এক্সিকিউশন । এটি মূলত বলেছে যে জাভা প্রতিটি ক্রিয়াকলাপের জন্য একটি বস্তুর প্রয়োজন, এবং তাই ফাংশন পয়েন্টারগুলির মতো "ক্রিয়া-কেবল" সত্তা নেই।


8

অনুরূপ কার্যকারিতা অর্জন করতে আপনি বেনামে অভ্যন্তরীণ ক্লাস ব্যবহার করতে পারেন।

আপনি যদি একটি ইন্টারফেস সংজ্ঞায়িত করতে চান 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.
    }
}

7

জাভা 8 ল্যাম্বডাস এবং পদ্ধতি রেফারেন্স চালু করেছে । সুতরাং যদি আপনার ফাংশন কোনও ক্রিয়ামূলক ইন্টারফেসের সাথে মেলে (আপনি নিজের তৈরি করতে পারেন) আপনি এই ক্ষেত্রে কোনও পদ্ধতি রেফারেন্স ব্যবহার করতে পারেন।

জাভা সাধারণ ফাংশনাল ইন্টারফেসের একটি সেট সরবরাহ করে । যেখানে আপনি নিম্নলিখিতটি করতে পারেন:

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

সেখানে কি এর একটি ধারণা আছে alias: যেমন public List<T> collect(T t) = Collections::collect
জাভদ্বা

@ জাভাদ্বা যতদূর জানি না।
অ্যালেক্স

5

জাভাতে তেমন কিছুই নেই। আপনাকে সেই অবজেক্টের পদ্ধতিতে রেফারেন্সটি পাস করার জন্য আপনার ফাংশনটি কোনও অবজেক্টে আবৃত করতে হবে এবং সেই বস্তুর রেফারেন্সটি পাস করতে হবে।

কৃত্রিমভাবে, স্থান নির্ধারিত বেনাম শ্রেণি বা শ্রেণীর সদস্য ভেরিয়েবল হিসাবে সংজ্ঞায়িত বেনাম শ্রেণি ব্যবহার করে এটি একটি নির্দিষ্ট পরিমাণে সহজ করা যায়।

উদাহরণ:

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

3

আমি জাভাতে প্রতিবিম্ব ব্যবহার করে কলব্যাক / প্রতিনিধি সমর্থন বাস্তবায়ন করেছি। বিশদ এবং কার্যকারী উত্স আমার ওয়েবসাইটে উপলব্ধ

কিভাবে এটা কাজ করে

উইথপার্মস নামে নেস্টেড ক্লাস সহ আমাদের কলব্যাক নামের একটি নীতিগত ক্লাস রয়েছে। যে এপিআই কলব্যাকের প্রয়োজন তা প্যারামিটার হিসাবে একটি কলব্যাক অবজেক্ট নেবে এবং যদি প্রয়োজন হয় তবে একটি কল ভেরিয়েবল হিসাবে কলব্যাক তৈরি করবে ith যেহেতু এই বস্তুর অনেকগুলি অ্যাপ্লিকেশন পুনরাবৃত্ত হবে, এটি খুব পরিষ্কারভাবে কাজ করে।

পারফরম্যান্সটি এখনও আমার কাছে উচ্চ অগ্রাধিকারের সাথে, প্রতিটি অনুরোধের জন্য প্যারামিটারগুলি ধারণ করার জন্য আমার কোনও নিক্ষিপ্ত অবজেক্ট অ্যারে তৈরি করা প্রয়োজন হবে না - সর্বোপরি বড় ডেটা কাঠামোতে হাজার হাজার উপাদান থাকতে পারে এবং একটি বার্তা প্রক্রিয়াকরণে পরিস্থিতি আমরা কয়েক সেকেন্ডে হাজার হাজার ডেটা স্ট্রাকচার প্রক্রিয়াকরণ করতে পারি।

থ্রেডসেফ হওয়ার জন্য প্যারামিটার অ্যারেটি এপিআই পদ্ধতির প্রতিটি অনুরোধের জন্য স্বতন্ত্রভাবে থাকা প্রয়োজন, এবং দক্ষতার জন্য কলব্যাকের প্রতিটি অনুরোধের জন্য একই ব্যবহার করা উচিত; আমার একটি দ্বিতীয় অবজেক্টের প্রয়োজন ছিল যা অনুরোধের জন্য প্যারামিটার অ্যারের সাথে কলব্যাককে আবদ্ধ করার জন্য তৈরি করা সস্তা। তবে, কিছু পরিস্থিতিতে, আমন্ত্রণকারীটির অন্যান্য কারণে ইতিমধ্যে একটি প্যারামিটার অ্যারে থাকবে। এই দুটি কারণে প্যারামিটার অ্যারে কলব্যাক অবজেক্টে অন্তর্ভুক্ত ছিল না। এছাড়াও অনুরোধের পছন্দ (একটি অ্যারের হিসাবে বা স্বতন্ত্র বস্তু হিসাবে প্যারামিটারগুলি পাস করা) API এর হাতে কলব্যাক ব্যবহার করে এটির অভ্যন্তরীণ কাজের জন্য উপযুক্ত যাহার প্রার্থনাটি সবচেয়ে উপযুক্ত উপযুক্ত তা কলব্যাকটি ব্যবহার করে using

উইথপার্মস নেস্টেড ক্লাস, তারপরে, এটি alচ্ছিক এবং দুটি উদ্দেশ্যে পরিবেশন করে, এতে কলব্যাক অনুরোধগুলির জন্য প্রয়োজনীয় প্যারামিটার অবজেক্ট অ্যারে রয়েছে এবং এটি 10 ​​ওভারলোডেড ইনভোক () পদ্ধতিগুলি (1 থেকে 10 পরামিতি সহ) সরবরাহ করে যা প্যারামিটার অ্যারে লোড করে এবং তারপরে কলব্যাক লক্ষ্য প্রার্থনা করুন।



-1

এখানকার বেশিরভাগ লোকের তুলনায় আমি জাভাতে নতুন, তবে যেহেতু আমি তেমন একটি পরামর্শ দেখিনি, আমার কাছে পরামর্শের আরও একটি বিকল্প আছে। আমি নিশ্চিত নই যে এটির একটি ভাল অনুশীলন কিনা, বা এমনকি আগে প্রস্তাব দেওয়া হয়েছিল এবং আমি এটি পেয়েছি না। আমি কেবল এটি পছন্দ করি যেহেতু আমি এর স্ব বর্ণনামূলক বলে মনে করি।

 /*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();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.