বেনাম ক্লাসে প্যারামিটারগুলি কীভাবে পাস করবেন?


146

প্যারামিটারগুলি পাস করা, বা কোনও বেনাম শ্রেণিতে বাহ্যিক পরামিতিগুলি অ্যাক্সেস করা সম্ভব? উদাহরণ স্বরূপ:

int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // How would one access myVariable here?
    }
});

শ্রোতাদের আসল নামী শ্রেণি হিসাবে তৈরি না করে শ্রোতার মাইভ্যারেবল অ্যাক্সেস করার বা মাইভ্যারেবল পাস করার কোনও উপায় আছে কি?


7
finalসংলগ্ন পদ্ধতি থেকে আপনি স্থানীয় ভেরিয়েবলগুলি উল্লেখ করতে পারেন ।
টম হাটিন - ২৪

আমি একটি ব্যক্তিগত পদ্ধতি যা ব্যক্তিগত myVariable উদাহরণস্বরূপ (গুলি) সূচনা এবং কারণে ফিরে বন্ধের বক্রবন্ধনী এ বলা যেতে পারে সংজ্ঞা অ্যাডাম Mmlodzinski এর পরামর্শ চেহারা পছন্দ করি this
dlamblin

এই প্রশ্নের কয়েকটি ভাগ করা লক্ষ্য রয়েছে: স্ট্যাকওভারফ্লো.com
অ্যালিস্টার ম্যাককর্ম্যাক

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

উত্তর:


78

প্রযুক্তিগতভাবে, না, কারণ বেনামে ক্লাসে কনস্ট্রাক্টর থাকতে পারে না।

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

সম্পাদনা করুন : পিটার যেমন উল্লেখ করেছেন, আপনি বেনাম শ্রেণীর সুপারক্লাসের নির্মাণকারীর কাছেও পরামিতিগুলি পাস করতে পারেন।


21
একটি বেনাম শ্রেণীর ব্যবহার তার পিতামাতার কনস্ট্রাক্টর ব্যবহার করে। উদাহরণস্বরূপnew ArrayList(10) { }
পিটার লরি

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


4
বেনামে ক্লাসে ইনস্ট্যান্স ইনিশিয়ালাইজার থাকতে পারে, যা বেনাম ক্লাসে প্যারামিটার-কম নির্মাতা হিসাবে কাজ করতে পারে। এগুলি ক্ষেত্রের কার্যভার হিসাবে একই ক্রমে কার্যকর করা হয়, যেমন super()প্রকৃত নির্মাণকারীর পরে এবং তার আগে। new someclass(){ fields; {initializer} fields; methods(){} }। এটি স্ট্যাটিক আরম্ভের মতো তবে স্ট্যাটিক কীওয়ার্ড ছাড়াই। docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.6
মার্ক জেরোনিমাস

এই স্ট্যাকওভারফ্লো.com/a/3045185/1737819 দেখুন এটি কনস্ট্রাক্টর ছাড়াই কীভাবে বাস্তবায়ন করা যায় তা বলে।
বিকাশকারী মারিয়াস ইলানাস

336

হ্যাঁ, একটি 'প্রাথমিক' পদ্ধতি যুক্ত করে এটি 'এটি' ফেরত দেয় এবং তত্ক্ষণাত্ সেই পদ্ধতিটি কল করে:

int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    private int anonVar;
    public void actionPerformed(ActionEvent e) {
        // How would one access myVariable here?
        // It's now here:
        System.out.println("Initialized with value: " + anonVar);
    }
    private ActionListener init(int var){
        anonVar = var;
        return this;
    }
}.init(myVariable)  );

কোনও 'চূড়ান্ত' ঘোষণার দরকার নেই।


4
বাহ ... উজ্জ্বল! আমি finalরেফারেন্স অবজেক্ট তৈরি করতে এতটাই ক্লান্ত হয়ে পড়েছি যাতে আমি আমার বেনাম ক্লাসে তথ্য পেতে পারি। ভাগ করার জন্য আপনাকে ধন্যবাদ!
ম্যাট ক্লিন

7
init()ফাংশনটি কেন ফিরে আসতে হবে this? আমি সিনট্যাক্সটি সত্যিই পাই না।
জোরি

11
কারণ আপনার myButton.addActionListener (...) একটি অ্যাকশনলিস্টনার অবজেক্টটিকে এমন একটি বস্তু হিসাবে প্রত্যাশা করে যা আপনি যখন তার পদ্ধতিটি কল করেন তখন ফিরে আসে।

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

2
সরল: প্রাইভেট ইন anonVar = myVariable;
আনম

29

হ্যাঁ. আপনি পরিবর্তনশীল ক্যাপচার করতে পারেন, অভ্যন্তর শ্রেণীর কাছে দৃশ্যমান। একমাত্র সীমাবদ্ধতা এটি হতে হবে চূড়ান্ত


বেনাম শ্রেণীর দ্বারা বর্ণিত ইনস্ট্যান্স ভেরিয়েবলগুলি চূড়ান্ত আফাইক হতে হবে না।
ম্যাথু উইলিস

8
ইনস্ট্যান্স ভেরিয়েবলগুলি রেফারেন্স করা হয় thisযার মাধ্যমে চূড়ান্ত।
পিটার লরি

আমি যদি পরিবর্তনটি পরিবর্তন করতে না চাই final? আমি কোন বিকল্প খুঁজে পাচ্ছি না। এটি উত্স পরামিতি প্রভাবিত করতে পারে যা ডিজাইন করা হয়েছে final
অ্যালস্টন

20

এটার মত:

final int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // Now you can access it alright.
    }
});

14

এটি যাদু করবে

int myVariable = 1;

myButton.addActionListener(new ActionListener() {

    int myVariable;

    public void actionPerformed(ActionEvent e) {
        // myVariable ...
    }

    public ActionListener setParams(int myVariable) {

        this.myVariable = myVariable;

        return this;
    }
}.setParams(myVariable));

8

Http://www.coderanch.com/t/567294/java/java/declare-constructor- বেনামে- ক্লাসে দেখানো হয়েছে আপনি একটি উদাহরণ ইনিশিয়ালাইজার যুক্ত করতে পারেন। এটি এমন একটি ব্লক যার নাম নেই এবং প্রথমে মৃত্যুদন্ড কার্যকর করা হয় (ঠিক যেমন একটি নির্মাণকারীর মতো)।

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


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

1
@ ম্যাটক্লেইন আমার কাছে মনে হচ্ছে এটি সমাধান করে। এটি আসলে একই জিনিস এবং কম ভার্বোস।
haelix

1
প্রশ্নটি ক্লাসে পরামিতিগুলি কীভাবে পাস করতে হবে তা জানতে চেয়েছিল, যেমন আপনি এমন কোনও নির্মাণকারীর সাথে যা প্যারামিটারগুলির প্রয়োজন requires লিঙ্কটি (যা এখানে সংক্ষিপ্ত করা উচিত ছিল) কেবলমাত্র কীভাবে প্যারামিটার-কম উদাহরণ ইনিশিয়ালাইজার থাকতে হবে, যা প্রশ্নের উত্তর দেয় না। এই কৌশলটি finalআভা দ্বারা বর্ণিত হিসাবে চলকগুলির সাথে ব্যবহার করা যেতে পারে , তবে এই উত্তরটি এই উত্তরটিতে সরবরাহ করা হয়নি। এতদূর, সর্বোত্তম উত্তর হ'ল অ্যাডাম মলডজিংসসি প্রদত্ত একটি (আমি এখন এই প্যাটার্নটি একচেটিয়াভাবে ব্যবহার করি, আরও ফাইনাল নেই!)। আমি আমার মন্তব্যে দাঁড়িয়েছি যে এটি জিজ্ঞাসিত প্রশ্নের উত্তর দেয় না।
ম্যাট ক্লেইন

7

আমার সমাধানটি এমন একটি পদ্ধতি ব্যবহার করা যা প্রয়োগ করা বেনাম শ্রেণীর ফিরিয়ে দেয়। নিয়মিত যুক্তি পদ্ধতিতে পাস করা যেতে পারে এবং বেনাম শ্রেণীর মধ্যে পাওয়া যায়।

উদাহরণস্বরূপ: (কিছু জিডব্লিউটি কোড থেকে একটি পাঠ্য বাক্স পরিবর্তন পরিচালনা করতে):

/* Regular method. Returns the required interface/abstract/class
   Arguments are defined as final */
private ChangeHandler newNameChangeHandler(final String axisId, final Logger logger) {

    // Return a new anonymous class
    return new ChangeHandler() {
        public void onChange(ChangeEvent event) {
            // Access method scope variables           
            logger.fine(axisId)
        }
     };
}

এই উদাহরণস্বরূপ, নতুন বেনাম শ্রেণীবদ্ধের সাথে উল্লেখ করা হবে:

textBox.addChangeHandler(newNameChangeHandler(myAxisName, myLogger))

বা , ওপি এর প্রয়োজনীয়তা ব্যবহার করে:

private ActionListener newActionListener(final int aVariable) {
    return new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Your variable is: " + aVariable);
        }
    };
}
...
int myVariable = 1;
newActionListener(myVariable);

এটি ভাল, এটি বেনাম শ্রেণিকে কয়েকটি সহজে চিহ্নিত করতে সক্ষম ভেরিয়েবলগুলিতে সীমাবদ্ধ করে এবং কিছু ভেরিয়েবলকে চূড়ান্ত করার জন্য জঘন্য আচরণ সরিয়ে দেয়।
দুর্বল পরিবর্তনশীল

3

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

আপনি যদি myVariableচূড়ান্ত হতে না চান তবে আপনাকে এটিকে একটি নতুন স্ক্যাপে গুটিয়ে রাখতে হবে যেখানে এটি চূড়ান্ত হলে তা গুরুত্বপূর্ণ নয়।

int myVariable = 1;

{
    final int anonVar = myVariable;

    myButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // How would one access myVariable here?
            // Use anonVar instead of myVariable
        }
    });
}

অ্যাডাম ম্লোডজিনস্কি তার উত্তরে কিন্তু আরও কিছু কোড সহ কিছু করেন না।


এটি এখনও অতিরিক্ত সুযোগ ছাড়াই কাজ করে। এটি চূড়ান্তভাবে অন্যান্য উত্তরগুলির মতো কার্যকরভাবে একই।
অ্যাডাম ম্লোডজিনস্কি

@ অ্যাডামম্লোডজিনস্কি না এটি কার্যকরভাবে আপনার উত্তর হিসাবে একই, কারণ এটি একটি ব্যক্তিগত সুযোগে মূল ভেরিয়েবলের মান সহ একটি নতুন ভেরিয়েবল প্রবর্তন করে।
সিভিং

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

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

finalভেরিয়েবল সলিউশন ব্যবহার করার চেয়ে এটি কীভাবে আলাদা তা আমি দেখতে পাচ্ছি না ।
কেভিন রাভ

3

আপনি সরল ল্যাম্বডাস ব্যবহার করতে পারেন ("ল্যাম্বডা এক্সপ্রেশনগুলি ভেরিয়েবলগুলি ক্যাপচার করতে পারে")

int myVariable = 1;
ActionListener al = ae->System.out.println(myVariable);
myButton.addActionListener( al );

এমনকি একটি ফাংশন

Function<Integer,ActionListener> printInt = 
    intvar -> ae -> System.out.println(intvar);

int myVariable = 1;
myButton.addActionListener( printInt.apply(myVariable) );

রিফ্যাক্টর সজ্জিত এবং অ্যাডাপ্টারগুলির ফাংশন ব্যবহার করা দুর্দান্ত উপায় Using এখানে দেখুন

আমি সবেমাত্র ল্যাম্বডাস সম্পর্কে শিখতে শুরু করেছি, সুতরাং আপনার যদি কোনও ভুল হয় তবে একটি মন্তব্য লিখতে নির্দ্বিধায়।


1

বাহ্যিক ভেরিয়েবলে কিছু মান রাখার একটি সহজ উপায় (বেনামে শ্রেণীর অন্তর্ভুক্ত নয়) হ'ল ফলো!

একইভাবে আপনি যদি একটি বাহ্যিক ভেরিয়েবলের মান পেতে চান তবে আপনি এমন একটি পদ্ধতি তৈরি করতে পারেন যা আপনি যা চান ফিরে আসে!

public class Example{

    private TypeParameter parameter;

    private void setMethod(TypeParameter parameter){

        this.parameter = parameter;

    }

    //...
    //into the anonymus class
    new AnonymusClass(){

        final TypeParameter parameterFinal = something;
        //you can call setMethod(TypeParameter parameter) here and pass the
        //parameterFinal
        setMethod(parameterFinal); 

        //now the variable out the class anonymus has the value of
        //of parameterFinal

    });

 }

-2

আমি ভেবেছিলাম বেনাম শ্রেণীরা মূলত ল্যাম্বডাসের মতো ছিল তবে আরও খারাপ সিনট্যাক্সের সাথে ... এটি সত্য বলে প্রমাণিত হয়েছে তবে বাক্য গঠনটি আরও খারাপ এবং এর সমন্বিত শ্রেণীর মধ্যে স্থানীয় ভেরিয়েবলগুলি বেরিয়ে যাওয়ার কারণ ঘটায়।

আপনি প্যারেন্ট ক্লাসের ক্ষেত্রগুলিতে তৈরি করে কোনও চূড়ান্ত পরিবর্তনশীল অ্যাক্সেস করতে পারবেন না।

যেমন

ইন্টারফেস:

public interface TextProcessor
{
    public String Process(String text);
}

শ্রেণী:

private String _key;

public String toJson()
{
    TextProcessor textProcessor = new TextProcessor() {
        @Override
        public String Process(String text)
        {
            return _key + ":" + text;
        }
    };

    JSONTypeProcessor typeProcessor = new JSONTypeProcessor(textProcessor);

    foreach(String key : keys)
    {
        _key = key;

        typeProcessor.doStuffThatUsesLambda();
    }

আমি জানি না যে তারা জাভা 8 এ এটি বাছাই করেছেন (আমি EE বিশ্বে আটকেছি এবং এখনও 8 পেয়েছি না) তবে সি # তে এটি দেখতে দেখতে এটি দেখতে পাবেন:

    public string ToJson()
    {
        string key = null;
        var typeProcessor = new JSONTypeProcessor(text => key + ":" + text);

        foreach (var theKey in keys)
        {
            key = theKey;

            typeProcessor.doStuffThatUsesLambda();
        }
    }

আপনার # সিতে পৃথক ইন্টারফেসের দরকার নেই ... আমি এটি মিস করছি! আমি নিজেকে জাভাতে আরও খারাপ ডিজাইন তৈরি করতে এবং নিজেকে আরও পুনরাবৃত্তি করতে দেখছি কারণ যে কোনও কোডের পুনরায় ব্যবহার করতে আপনার জাভাতে যে পরিমাণ কোড + জটিলতা যুক্ত করতে হবে তা কেবল অনুলিপি করা এবং অনেক সময় আটকানোর চেয়ে খারাপ।


দেখতে পাবেন এমন অন্য হ্যাকের মতো দেখতে এখানে একটি উপাদান অ্যারে ব্যবহার করা উচিত
stackoverflow.com/a/4732586/962696
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.