প্যারামিটার হিসাবে জাভা পাস পদ্ধতি


277

আমি রেফারেন্স দিয়ে কোনও পদ্ধতি পাস করার উপায় খুঁজছি। আমি বুঝতে পারি যে জাভা প্যারামিটার হিসাবে পদ্ধতিগুলি পাস করে না, তবে আমি একটি বিকল্প পেতে চাই।

আমাকে বলা হয়েছে ইন্টারফেসগুলি প্যারামিটার হিসাবে পাস করার পদ্ধতিগুলির বিকল্প, তবে আমি বুঝতে পারি না যে কোনও ইন্টারফেস কীভাবে রেফারেন্স দ্বারা কোনও পদ্ধতি হিসাবে কাজ করতে পারে। যদি আমি সঠিকভাবে বুঝতে পারি তবে একটি ইন্টারফেস হ'ল একটি বিমূর্ত পদ্ধতির সেট যা সংজ্ঞায়িত হয় না। আমি এমন একটি ইন্টারফেস পাঠাতে চাই না যা প্রতিবার সংজ্ঞায়িত করা দরকার কারণ বিভিন্ন পন্থাগুলি একই পরামিতিগুলির সাথে একই পদ্ধতিতে কল করতে পারে।

আমি যেটি সম্পাদন করতে চাই তা হ'ল এটির অনুরূপ:

public void setAllComponents(Component[] myComponentArray, Method myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod(leaf);
    } //end looping through components
}

অনুরোধ করা যেমন:

setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());

এখনই আমার সমাধানটি হল একটি অতিরিক্ত প্যারামিটার পাস করা এবং উপযুক্ত পদ্ধতিটি নির্বাচন করার জন্য ভিতরে একটি স্যুইচ কেস ব্যবহার করা। তবে কোডটি পুনরায় ব্যবহারের সময় এই সমাধানটি ndণ দেয় না।

আরও দেখুন এই উত্তর stackoverflow.com/a/22933032/1010868 অনুরূপ প্রশ্নের জন্য
Tomasz Gawel

উত্তর:


233

সম্পাদনা করুন : জাভা 8 হিসাবে, ল্যাম্বডা এক্সপ্রেশনগুলি একটি দুর্দান্ত সমাধান হিসাবে অন্যান্য উত্তরগুলি নির্দেশ করেছে। নীচের উত্তরটি জাভা 7 এবং এর আগে লেখা হয়েছিল ...


কটাক্ষপাত কমান্ড প্যাটার্ন

// NOTE: code not tested, but I believe this is valid java...
public class CommandExample 
{
    public interface Command 
    {
        public void execute(Object data);
    }

    public class PrintCommand implements Command 
    {
        public void execute(Object data) 
        {
            System.out.println(data.toString());
        }    
    }

    public static void callCommand(Command command, Object data) 
    {
        command.execute(data);
    }

    public static void main(String... args) 
    {
        callCommand(new PrintCommand(), "hello world");
    }
}

সম্পাদনা করুন: পিট কির্খাম যেমন উল্লেখ করেছে , একজন দর্শনার্থী ব্যবহার করে এটি করার আরও একটি উপায় রয়েছে । দর্শনার্থীর দৃষ্টিভঙ্গিটি আরও কিছুটা জড়িত - আপনার নোডগুলিকে কোনও acceptVisitor()পদ্ধতির সাথে দর্শকের সচেতন হওয়া দরকার - তবে যদি আপনাকে আরও জটিল অবজেক্টের গ্রাফটি অতিক্রম করতে হয় তবে তা পরীক্ষা করার মতো।


2
@ ম্যাক - ভাল! এগুলি প্রথম শ্রেণীর পদ্ধতি ছাড়াই ভাষাগুলিতে পুনরায় উঠে আসে তাদের অনুকরণের ডি-ফ্যাক্টো উপায় হিসাবে, তাই এটি মনে রাখার মতো।
ড্যান ভিন্টন

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

না, আপনি কেবলমাত্র গ্রহণের পদ্ধতিটি প্রয়োজন যদি আপনি ডাবল প্রেরণের সাথে ভিজিটের সমন্বয় করে থাকেন। আপনার যদি মনোমরফিক দর্শনার্থী থাকে তবে এটি ঠিক উপরের কোডটি।
পিট কিরখাম

জাভা 8-তে ex.operS এর মতো হতে পারে (স্ট্রিং :: টু লোয়ারক্যাস, "STRING")। সুন্দর নিবন্ধটি দেখুন: স্টাডিট্রিলস
জোন

পিট কির্খামটি সঠিক: আপনার কোডটি কমান্ড প্যাটার্ন নয়, ভিজিটর প্যাটার্ন প্রয়োগ করছে (এবং এটি ওপি যেমন প্রয়োজন তেমনই ভাল)) পিট যেমন বলেছেন, আপনি যুক্তিটি আবদ্ধ করছেন না, সুতরাং আপনি কমান্ড করছেন না - আপনার আদেশ ইন্টারফেসের একটি এক্সিকিউট রয়েছে যা একটি পরামিতি নেয়। উইকিপিডিয়া না। এটি কমান্ড প্যাটার্নের উদ্দেশ্যটির জন্য মৌলিক। যেমন প্রথম অনুচ্ছেদে বলা হয়েছে " সমস্ত তথ্য encapsulate ... এই তথ্যের মধ্যে পদ্ধতির নাম অন্তর্ভুক্ত রয়েছে, পদ্ধতিটির পরামিতিগুলির জন্য যে পদ্ধতিটি এবং পদ্ধতির মান রয়েছে ।"
টুলমেকারস্টেভ

73

জাভা 8-এ, আপনি এখন ল্যাম্বদা এক্সপ্রেশন এবং পদ্ধতি রেফারেন্সগুলি ব্যবহার করে আরও সহজে কোনও পদ্ধতি পাস করতে পারেন । প্রথমত, কিছু ব্যাকগ্রাউন্ড: একটি কার্যনির্বাহী ইন্টারফেস একটি ইন্টারফেস যা একটি এবং কেবল একটি বিমূর্ত পদ্ধতি রয়েছে যদিও এটিতে অনেকগুলি ডিফল্ট পদ্ধতি থাকতে পারে (জাভা 8-এ নতুন) এবং স্থিতিশীল পদ্ধতি থাকতে পারে। ল্যাম্বডা এক্সপ্রেশনটি যদি আপনি ল্যাম্বডা এক্সপ্রেশনটি ব্যবহার না করেন তবে সমস্ত অপ্রয়োজনীয় বাক্য গঠন ছাড়াই দ্রুত বিমূর্ত পদ্ধতিটি প্রয়োগ করতে পারে।

ল্যাম্বদা এক্সপ্রেশন ছাড়াই:

obj.aMethod(new AFunctionalInterface() {
    @Override
    public boolean anotherMethod(int i)
    {
        return i == 982
    }
});

ল্যাম্বদা এক্সপ্রেশন সহ:

obj.aMethod(i -> i == 982);

লাম্বদা এক্সপ্রেশনগুলিতে জাভা টিউটোরিয়ালটির একটি অংশ এখানে দেওয়া হয়েছে :

ল্যাম্বদা এক্সপ্রেশনগুলির সিনট্যাক্স

একটি ল্যাম্বডা এক্সপ্রেশন নিম্নলিখিতটি নিয়ে গঠিত:

  • ক্যারেটেসিতে আবদ্ধ ফর্মাল প্যারামিটারগুলির একটি কমা-বিচ্ছিন্ন তালিকা। চেকপারসন.টেস্ট পদ্ধতিতে একটি প্যারামিটার, পি রয়েছে, যা ব্যক্তি শ্রেণির উদাহরণ উপস্থাপন করে।

    দ্রষ্টব্য : আপনি ল্যাম্বডা এক্সপ্রেশনটিতে প্যারামিটারগুলির ডেটা ধরণ বাদ দিতে পারেন। এছাড়াও, যদি কেবলমাত্র একটি প্যারামিটার থাকে তবে আপনি প্রথম বন্ধনী বাদ দিতে পারেন। উদাহরণস্বরূপ, নিম্নলিখিত লাম্বদা এক্সপ্রেশনটিও বৈধ:

    p -> p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25
  • তীর টোকেন, ->

  • একটি দেহ, যা একটি একক অভিব্যক্তি বা বিবৃতি ব্লক সমন্বিত। এই উদাহরণটি নিম্নলিখিত প্রকাশটি ব্যবহার করে:

    p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25

    আপনি যদি একটি একক অভিব্যক্তি নির্দিষ্ট করে থাকেন তবে জাভা রানটাইম এক্সপ্রেশনটিকে মূল্যায়ন করে তার মানটি ফেরত দেয়। বিকল্পভাবে, আপনি একটি রিটার্ন বিবৃতি ব্যবহার করতে পারেন:

    p -> {
        return p.getGender() == Person.Sex.MALE
            && p.getAge() >= 18
            && p.getAge() <= 25;
    }

    একটি রিটার্ন বিবৃতি একটি অভিব্যক্তি নয়; ল্যাম্বডা এক্সপ্রেশনে আপনাকে অবশ্যই ব্রেসগুলি ({}) দ্বারা বিবৃতি আবদ্ধ করতে হবে। তবে, আপনাকে ধনুর্বন্ধনীগুলিতে একটি শূন্য পদ্ধতি আবদ্ধ করতে হবে না। উদাহরণস্বরূপ, নিম্নলিখিতটি একটি বৈধ ল্যাম্বডা এক্সপ্রেশন:

    email -> System.out.println(email)

নোট করুন যে একটি ল্যাম্বডা এক্সপ্রেশনটি অনেকটা পদ্ধতি ঘোষণার মতো দেখাচ্ছে; আপনি নামহীন পদ্ধতি হিসাবে ল্যাম্বডা এক্সপ্রেশন বিবেচনা করতে পারেন —


ল্যাম্বডা এক্সপ্রেশনটি ব্যবহার করে আপনি কীভাবে "একটি পদ্ধতি পাস" করতে পারেন তা এখানে:

interface I {
    public void myMethod(Component component);
}

class A {
    public void changeColor(Component component) {
        // code here
    }

    public void changeSize(Component component) {
        // code here
    }
}
class B {
    public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) {
        for(Component leaf : myComponentArray) {
            if(leaf instanceof Container) { // recursive call if Container
                Container node = (Container)leaf;
                setAllComponents(node.getComponents(), myMethodInterface);
            } // end if node
            myMethodsInterface.myMethod(leaf);
        } // end looping through components
    }
}
class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), component -> a.changeColor(component));
        b.setAllComponents(this.getComponents(), component -> a.changeSize(component));
    }
}

শ্রেণীর Cপাঠাগারটি আরও কিছুটা ছোট করা যেতে পারে যেমন পদ্ধতি রেফারেন্স ব্যবহার করে:

class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), a::changeColor);
        b.setAllComponents(this.getComponents(), a::changeSize);
    }
}

ক্লাস এ-এর ইন্টারফেসটি রূপান্তরিত হওয়া দরকার?
সেরোব_বি

1
@ সরব_বি না আপনি যদি এটিকে কোনও পদ্ধতি রেফারেন্স ( ::অপারেটর দেখুন) হিসাবে পাস করতে না চান তবে এ কী তা বিবেচনা করে না। a.changeThing(component)আপনি চান যে কোনও বিবৃতি বা কোড ব্লকে পরিবর্তন করা যেতে পারে, যতক্ষণ না এটি শূন্য হয়।
দি হাটের সাথে গাই

29

java.lang.reflect.Methodঅবজেক্ট এবং কলটি ব্যবহার করুনinvoke


12
দেখছি না কেন। প্রশ্নটি হল প্যারামিটার হিসাবে কোনও পদ্ধতি পাস করা এবং এটি এটি করার একটি খুব কার্যকর উপায়। এটি দেখতে দেখতে সুন্দর লাগার জন্য যে কোনও সংখ্যক চমত্কার চেহারার প্যাটার্নে আবৃত করা যেতে পারে। এটি কোনও সাধারণ ইন্টারফেসের প্রয়োজন ছাড়াই এটি জেনারিক।
বিনোধ রামশুভ্রমনিয়ান

3
আপনি কি জাভাস্ক্রিপ্ট এফগিতে সুরক্ষা টাইপ করেছেন? প্রকারের সুরক্ষা কোনও যুক্তি নয়।
ডানুবিয়ান নাবিক

13
যখন প্রশ্নে ভাষা টাইপ সুরক্ষাটিকে তার শক্তিশালী উপাদানগুলির মধ্যে একটি হিসাবে ধরে রাখে তখন কীভাবে প্রকার সুরক্ষা একটি যুক্তি নয়? জাভা একটি দৃ strongly়ভাবে টাইপ করা ভাষা এবং শক্তিশালী টাইপিং এটির কারণগুলির মধ্যে একটি কারণ যা আপনি এটি অন্য সংকলিত ভাষার তুলনায় বেছে নিতে পারেন।
অ্যাডাম পার্কিন 21

21
"মূল প্রতিবিম্ব সুবিধাটি মূলত উপাদান-ভিত্তিক অ্যাপ্লিকেশন নির্মাতাদের সরঞ্জামগুলির জন্য তৈরি করা হয়েছিল [ আইটেম 53: কার্যকর জাভা দ্বিতীয় সংস্করণ থেকে প্রতিচ্ছবি প্রতিচ্ছবিতে ইন্টারফেস পছন্দ করুন। - এটি জাভা নির্মাতাদের চিন্তাভাবনার রেখা ;-)
উইলহেম মেগানান

8
প্রতিবিম্বের ন্যায়সঙ্গত ব্যবহার নয়। আমি সমস্ত উত্সাহ দেখে ভীত হই। প্রতিচ্ছবি কখনও সাধারণ প্রোগ্রামিং প্রক্রিয়া হিসাবে ব্যবহার করার উদ্দেশ্যে ছিল না; অন্য কোনও পরিষ্কার সমাধান না থাকলে কেবল এটি ব্যবহার করুন।
টুলমেকারস্টেভ

22

জাভা 8-এর পর থেকে একটি Function<T, R>ইন্টারফেস ( ডক্স ) রয়েছে, যার পদ্ধতি রয়েছে

R apply(T t);

আপনি অন্যান্য ফাংশনগুলির পরামিতি হিসাবে ফাংশনগুলি পাস করতে এটি ব্যবহার করতে পারেন। টি হ'ল ফাংশনের ইনপুট প্রকার, আর রিটার্ন টাইপ।

আপনার উদাহরণে আপনাকে এমন একটি ফাংশন পাস করতে হবে যা Componentকোনও ইনপুট হিসাবে টাইপ করে এবং কিছুই দেয় না Void। এই ক্ষেত্রে Function<T, R>সেরা পছন্দ নয়, যেহেতু অকার্যকর টাইপের কোনও অটোবক্সিং নেই। আপনি যে ইন্টারফেসটির সন্ধান করছেন সেটিকে পদ্ধতির সাথে ডকসConsumer<T> ( ডক্স ) বলা হয়

void accept(T t);

এটি দেখতে এটি দেখতে হবে:

public void setAllComponents(Component[] myComponentArray, Consumer<Component> myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { 
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } 
        myMethod.accept(leaf);
    } 
}

এবং আপনি এটিকে পদ্ধতির উল্লেখগুলি ব্যবহার করে কল করবেন:

setAllComponents(this.getComponents(), this::changeColor);
setAllComponents(this.getComponents(), this::changeSize); 

ধরে নিই যে আপনি একই শ্রেণিতে চেঞ্জারকলার () এবং চেঞ্জ সাইজ () পদ্ধতিগুলি সংজ্ঞায়িত করেছেন।


যদি আপনার পদ্ধতিটি একাধিক প্যারামিটার গ্রহণ করে, আপনি ব্যবহার করতে পারেন BiFunction<T, U, R>- টি এবং ইউ ইনপুট পরামিতিগুলির প্রকার এবং আর রিটার্নের ধরণ। এছাড়াও রয়েছে BiConsumer<T, U>(দুটি যুক্তি, কোনও রিটার্নের ধরণ নেই)। দুর্ভাগ্যক্রমে 3 এবং আরও ইনপুট পরামিতিগুলির জন্য, আপনাকে নিজের দ্বারা একটি ইন্টারফেস তৈরি করতে হবে। উদাহরণ স্বরূপ:

public interface Function4<A, B, C, D, R> {

    R apply(A a, B b, C c, D d);
}

19

প্যারামিটার হিসাবে আপনি যে পদ্ধতিটি পাস করতে চান তার সাথে প্রথমে একটি ইন্টারফেস সংজ্ঞায়িত করুন

public interface Callable {
  public void call(int param);
}

পদ্ধতি সহ একটি শ্রেণি প্রয়োগ করুন

class Test implements Callable {
  public void call(int param) {
    System.out.println( param );
  }
}

// অনুরোধ করুন

Callable cmd = new Test();

এটি আপনাকে প্যারামিটার হিসাবে সেমিডি পাস করতে এবং ইন্টারফেসে নির্ধারিত মেথড কলটি শুরু করতে দেয়

public invoke( Callable callable ) {
  callable.call( 5 );
}

1
আপনার নিজের জন্য ইন্টারফেস তৈরি করতে হবে না কারণ জাভা আপনার জন্য তাদের অনেকগুলি সংজ্ঞায়িত করেছে: ডকস.অরাকল.com
স্লিম

@ স্লিম ইন্টারেস্টিং পয়েন্ট, এই সংজ্ঞাগুলি কতটা স্থিতিশীল, সেগুলি কি আপনার প্রস্তাব অনুসারে প্রথাগতভাবে ব্যবহার করার ইচ্ছা রয়েছে, নাকি ভেঙে যাওয়ার সম্ভাবনা রয়েছে?
ম্যানুয়েল

@ স্লিম প্রকৃতপক্ষে, ডক্স উত্তর দেয় যে: "এই প্যাকেজের ইন্টারফেসগুলি জেডিকে দ্বারা ব্যবহৃত সাধারণ উদ্দেশ্যে কার্যকরী ইন্টারফেস এবং ব্যবহারকারী কোড দ্বারা এটি ব্যবহারের জন্য উপলব্ধ" "
ম্যানুয়েল

14

যদিও এটি জাভা 7 এবং নীচে এখনও বৈধ নয়, আমি বিশ্বাস করি যে আমাদের ভবিষ্যতের দিকে নজর দেওয়া উচিত এবং কমপক্ষে পরিবর্তনগুলি স্বীকৃতি দেওয়া উচিত জাভা 8 এর মতো নতুন সংস্করণে আসা দেওয়া উচিত।

যথা, এই নতুন সংস্করণটি জাভাতে ল্যাম্বডাস এবং পদ্ধতির রেফারেন্স নিয়ে আসে ( নতুন এপিআইগুলির সাথে) , যা এই সমস্যার আরেকটি বৈধ সমাধান they যদিও তাদের এখনও একটি ইন্টারফেসের প্রয়োজন হলে কোনও নতুন অবজেক্ট তৈরি করা হয় নি, এবং অতিরিক্ত শ্রেণিবদ্ধগুলি পৃথক কারণে আউটপুট ডিরেক্টরিকে দূষিত করার প্রয়োজন নেই need জেভিএম দ্বারা পরিচালিত।

উভয় স্বাদ (ল্যাম্বদা এবং পদ্ধতির রেফারেন্স) এর জন্য একটি একক পদ্ধতিতে একটি ইন্টারফেসের প্রয়োজন যা এর স্বাক্ষর ব্যবহার করা হয়:

public interface NewVersionTest{
    String returnAString(Object oIn, String str);
}

পদ্ধতির নাম এখান থেকে গুরুত্বপূর্ণ হবে না। যেখানে একটি ল্যাম্বদা গৃহীত হয়, সেখানে একটি পদ্ধতি রেফারেন্সও হয়। উদাহরণস্বরূপ, আমাদের স্বাক্ষরটি এখানে ব্যবহার করতে:

public static void printOutput(NewVersionTest t, Object o, String s){
    System.out.println(t.returnAString(o, s));
}

ল্যাম্বদা 1 পাস না হওয়া অবধি এটি কেবল একটি সাধারণ ইন্টারফেস অনুরোধ :

public static void main(String[] args){
    printOutput( (Object oIn, String sIn) -> {
        System.out.println("Lambda reached!");
        return "lambda return";
    }
    );
}

এটি আউটপুট দেবে:

Lambda reached!
lambda return

পদ্ধতির উল্লেখগুলি একই রকম similar প্রদত্ত:

public class HelperClass{
    public static String testOtherSig(Object o, String s){
        return "real static method";
    }
}

এবং প্রধান:

public static void main(String[] args){
    printOutput(HelperClass::testOtherSig);
}

আউটপুট হবে real static methodপদ্ধতির উল্লেখগুলি স্থির, উদাহরণস্বরূপ, স্বেচ্ছাসেবী দৃষ্টান্তগুলির সাথে অ স্ট্যাটিক এবং এমনকি নির্মাণকারীও হতে পারে । কনস্ট্রাক্টর এর মতো কিছুClassName::new ব্যবহার হবে।

1 এটি কিছু দ্বারা ল্যাম্বডা হিসাবে বিবেচিত হয় না, কারণ এর পার্শ্ব প্রতিক্রিয়া রয়েছে। এটি উদাহরণস্বরূপ, আরও বেশি সোজা-ভিজ্যুয়ালাইজড ফ্যাশনে একটির ব্যবহার।


12

গতবার আমি যাচাই করেছিলাম, জাভা আপনি যা চান তা স্থানীয়ভাবে করতে সক্ষম নয়; এই জাতীয় সীমাবদ্ধতা পেতে আপনাকে 'ওয়ার্ক-এভারসডস' ব্যবহার করতে হবে। যতদূর আমি এটি দেখতে পাচ্ছি, ইন্টারফেসগুলি একটি বিকল্প, তবে একটি ভাল বিকল্প নয়। সম্ভবত যে কেউ আপনাকে বলেছিল যে এটি এর অর্থ কিছু ছিল:

public interface ComponentMethod {
  public abstract void PerfromMethod(Container c);
}

public class ChangeColor implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public class ChangeSize implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public void setAllComponents(Component[] myComponentArray, ComponentMethod myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod.PerfromMethod(leaf);
    } //end looping through components
}

যার সাথে আপনি তখন অনুরোধ করবেন:

setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());

6

আপনার যদি কিছু ফেরত দেওয়ার জন্য এই পদ্ধতিগুলির প্রয়োজন না হয় তবে আপনি এগুলি চালানোর যোগ্য বস্তুগুলিকে ফিরিয়ে আনতে পারেন।

private Runnable methodName (final int arg) {
    return (new Runnable() {
        public void run() {
          // do stuff with arg
        }
    });
}

তারপরে এটি ব্যবহার করুন:

private void otherMethodName (Runnable arg){
    arg.run();
}

2

java.util.function.Functionপরামিতি ফাংশন হিসাবে সহজ পদ্ধতির জন্য কীভাবে ব্যবহার করতে হয় সে সম্পর্কে আমার পক্ষে যথেষ্ট স্পষ্ট কোনও উদাহরণ খুঁজে পাইনি । এখানে একটি সহজ উদাহরণ:

import java.util.function.Function;

public class Foo {

  private Foo(String parameter) {
    System.out.println("I'm a Foo " + parameter);
  }

  public static Foo method(final String parameter) {
    return new Foo(parameter);
  }

  private static Function parametrisedMethod(Function<String, Foo> function) {
    return function;
  }

  public static void main(String[] args) {
    parametrisedMethod(Foo::method).apply("from a method");
  }
}

মূলত আপনার Fooডিফল্ট কনস্ট্রাক্টরের সাথে একটি অবজেক্ট থাকে। একটি methodথেকে একটি প্যারামিটার হিসাবে বলা হবে parametrisedMethodধরনের যা Function<String, Foo>

  • Function<String, Foo>এর অর্থ হল যে ফাংশনটি Stringপ্যারামিটার হিসাবে গ্রহণ করে এবং এটিকে ফেরত দেয় Foo
  • Foo::Methodমত একটি ল্যামডা মিলাx -> Foo.method(x);
  • parametrisedMethod(Foo::method) হিসাবে দেখা যেতে পারে x -> parametrisedMethod(Foo.method(x))
  • .apply("from a method")করতে মূলতparametrisedMethod(Foo.method("from a method"))

যা এরপরে আউটপুটটিতে ফিরে আসবে:

>> I'm a Foo from a method

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


অ্যান্ড্রয়েডে আবেদন কলটি ব্যবহার করতে আপনার ন্যূনতম এপিআই 24
ইনেস বেলহোচেট

1

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

public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled)
{
...
Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist);
...
}

1

আমি জাভা বিশেষজ্ঞ নই তবে আপনার সমস্যাটি আমি এর মতো সমাধান করি:

@FunctionalInterface
public interface AutoCompleteCallable<T> {
  String call(T model) throws Exception;
}

আমি আমার বিশেষ ইন্টারফেসে প্যারামিটারটি সংজ্ঞায়িত করি

public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
//call here
String value = getSearchText.call(item);
...
}

অবশেষে, আমি বাস্তবায়ন getSearchText পদ্ধতি কলিং যখন আরম্ভ পদ্ধতি।

initialize(getMessageContactModelList(), new AutoCompleteCallable() {
          @Override
          public String call(Object model) throws Exception {
            return "custom string" + ((xxxModel)model.getTitle());
          }
        })

আসলে এটি সর্বোত্তম উত্তর এবং এটি করার সঠিক উপায়। আরও +1
amdev

0

পর্যবেক্ষক প্যাটার্ন ব্যবহার করুন (কখনও কখনও শ্রোতার ধরণও বলা হয়):

interface ComponentDelegate {
    void doSomething(Component component);
}

public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) {
    // ...
    delegate.doSomething(leaf);
}

setAllComponents(this.getComponents(), new ComponentDelegate() {
                                            void doSomething(Component component) {
                                                changeColor(component); // or do directly what you want
                                            }
                                       });

new ComponentDelegate()... ইন্টারফেস প্রয়োগকারী একটি বেনামি ধরণের ঘোষণা করে।


8
আপনি যে প্যাটার্নটি সন্ধান করছেন এটি এটি নয়।
পিট কিরখাম

1
পর্যবেক্ষক প্যাটার্নটি পরিবর্তনের প্রতিক্রিয়া জানাতে সক্ষমতার বিমূর্ততা সম্পর্কে। ওপি সংগ্রহের উপরে পুনরাবৃত্তি হওয়া কোড থেকে দূরে সংগ্রহের প্রতিটি আইটেমের করা পদক্ষেপটি বিমূর্ত করতে চায়, এটি দর্শকের বিন্যাস।
পিট কিরখাম

পর্যবেক্ষক / শ্রোতা প্যাটার্ন আসলে সেই আদেশ প্যাটার্নের মতো। তারা কেবল নিয়ত মধ্যে পৃথক। কমান্ডটি প্রথম শ্রেণির ফাংশন / ল্যাম্বডাসের বিকল্প হিসাবে পর্যবেক্ষক বিজ্ঞপ্তি সম্পর্কে রয়েছে। অন্যদিকে দর্শক সম্পূর্ণ আলাদা কিছু। আমি মনে করি না এটা বাক্য কয়েক ব্যাখ্যা করা যেতে পারে তাই দয়া কটাক্ষপাত আছে en.wikipedia.org/wiki/Visitor_pattern
EricSchaefer

0

এখানে একটি প্রাথমিক উদাহরণ:

public class TestMethodPassing
{
    private static void println()
    {
        System.out.println("Do println");
    }

    private static void print()
    {
        System.out.print("Do print");
    }

    private static void performTask(BasicFunctionalInterface functionalInterface)
    {
        functionalInterface.performTask();
    }

    @FunctionalInterface
    interface BasicFunctionalInterface
    {
        void performTask();
    }

    public static void main(String[] arguments)
    {
        performTask(TestMethodPassing::println);
        performTask(TestMethodPassing::print);
    }
}

আউটপুট:

Do println
Do print

0

আমি এখানে কোনও সমাধান পাই নি যা দেখায় যে কোনও পদ্ধতির পরামিতি হিসাবে আবদ্ধ পরামিতিগুলির সাথে কীভাবে পদ্ধতিটি পাস করতে হয়। বেলো হল প্যারামিটার মানগুলির সাথে ইতিমধ্যে আবদ্ধ কোনও পদ্ধতিটি কীভাবে পাস করতে পারবেন তার উদাহরণ।

  1. পদক্ষেপ 1: দুটি রিটার্ন টাইপ সহ দুটি ইন্টারফেস তৈরি করুন, অন্যটি ছাড়াই। জাভাতে একই রকম ইন্টারফেস রয়েছে তবে এগুলি ব্যবহারিক ব্যবহারের খুব কম কারণ তারা ব্যতিক্রমী ছোঁড়া সমর্থন করে না।


    public interface Do {
    void run() throws Exception;
    }


    public interface Return {
        R run() throws Exception;
    }
  1. লেনদেনে পদ্ধতি কল মোড়ানোর জন্য আমরা উভয় ইন্টারফেস কীভাবে ব্যবহার করি তার উদাহরণ। মনে রাখবেন যে আমরা প্রকৃত পরামিতিগুলির সাথে পদ্ধতিটি পাস করি।


    //example - when passed method does not return any value
    public void tx(final Do func) throws Exception {
        connectionScope.beginTransaction();
        try {
            func.run();
            connectionScope.commit();
        } catch (Exception e) {
            connectionScope.rollback();
            throw e;
        } finally {
            connectionScope.close();
        }
    }

    //Invoke code above by 
    tx(() -> api.delete(6));

অন্য একটি উদাহরণ দেখায় যে কীভাবে এমন কোনও পদ্ধতি পাস করতে হয় যা আসলে কিছু ফেরত দেয়



        public  R tx(final Return func) throws Exception {
    R r=null;
    connectionScope.beginTransaction();
    try {
                r=func.run();
                connectionScope.commit();
            } catch (Exception e) {
                connectionScope.rollback();
                throw e;
            } finally {
                connectionScope.close();
            }
        return r;
        }
        //Invoke code above by 
        Object x= tx(() -> api.get(id));

0

প্রতিবিম্ব সহ সমাধানের উদাহরণ, উত্তীর্ণ পদ্ধতিটি সর্বজনীন হতে হবে

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Program {
    int i;

    public static void main(String[] args) {
        Program   obj = new Program();    //some object

        try {
            Method method = obj.getClass().getMethod("target");
            repeatMethod( 5, obj, method );
        } 
        catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            System.out.println( e ); 
        }
    }

    static void repeatMethod (int times, Object object, Method method)
        throws IllegalAccessException, InvocationTargetException {

        for (int i=0; i<times; i++)
            method.invoke(object);
    }
    public void target() {                 //public is necessary
        System.out.println("target(): "+ ++i);
    }
}

0

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

ধারণাটি হ'ল স্বাক্ষরে ফাংশনটির রিটার্ন টাইপ ব্যবহার করা, যার অর্থ ফলন স্থির থাকতে হবে।

নীচে একটি ফাংশন যা একটি সময়সীমা সহ একটি প্রক্রিয়া চালায়।

public static void timeoutFunction(String fnReturnVal) {

    Object p = null; // whatever object you need here

    String threadSleeptime = null;

    Config config;

    try {
        config = ConfigReader.getConfigProperties();
        threadSleeptime = config.getThreadSleepTime();

    } catch (Exception e) {
        log.error(e);
        log.error("");
        log.error("Defaulting thread sleep time to 105000 miliseconds.");
        log.error("");
        threadSleeptime = "100000";
    }

    ExecutorService executor = Executors.newCachedThreadPool();
    Callable<Object> task = new Callable<Object>() {
        public Object call() {
            // Do job here using --- fnReturnVal --- and return appropriate value
            return null;
        }
    };
    Future<Object> future = executor.submit(task);

    try {
        p = future.get(Integer.parseInt(threadSleeptime), TimeUnit.MILLISECONDS);
    } catch (Exception e) {
        log.error(e + ". The function timed out after [" + threadSleeptime
                + "] miliseconds before a response was received.");
    } finally {
        // if task has started then don't stop it
        future.cancel(false);
    }
}

private static String returnString() {
    return "hello";
}

public static void main(String[] args) {
    timeoutFunction(returnString());
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.