জাভাতে কোনও পদ্ধতির ভিতরে শ্রেণি সংজ্ঞা ব্যবহার


105

উদাহরণ:

public class TestClass {

    public static void main(String[] args) {
        TestClass t = new TestClass();
    }

    private static void testMethod() {
        abstract class TestMethod {
            int a;
            int b;
            int c;

            abstract void implementMe();
        }

        class DummyClass extends TestMethod {
            void implementMe() {}
        }

        DummyClass dummy = new DummyClass();
    }
}

আমি খুঁজে পেয়েছি যে উপরের কোডটির টুকরোটি জাভাতে পুরোপুরি আইনী। আমি নিম্নলিখিত প্রশ্ন আছে।

  1. কোনও পদ্ধতির অভ্যন্তরে শ্রেণিক সংজ্ঞা রাখার ব্যবহার কী?
  2. এর জন্য কোনও শ্রেণি ফাইল তৈরি করা হবে DummyClass
  3. এই ধারণাটি অবজেক্ট ওরিয়েন্টেড পদ্ধতিতে কল্পনা করা আমার পক্ষে কঠিন। একটি আচরণের মধ্যে একটি বর্গ সংজ্ঞা আছে। সম্ভবত কেউ আমাকে সমমানের বাস্তব বিশ্বের উদাহরণ দিয়ে বলতে পারেন।
  4. কোনও পদ্ধতির অভ্যন্তরে অ্যাবস্ট্রাক্ট ক্লাসগুলি আমার কাছে কিছুটা উন্মাদ বলে মনে হয়। তবে কোনও ইন্টারফেসের অনুমতি নেই। এর পিছনে কি কোনও কারণ আছে?

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

7
কখনও কখনও এটি স্টাফ লুকিয়ে রাখার বিষয়ে আরও বেশি যা আপনার প্রয়োজনের চেয়ে আর কোথাও দরকার নেই;)
সরিমিসজ্যাকসন

উত্তর:


71

একে স্থানীয় শ্রেণি বলা হয়।

2 হ'ল সহজ: হ্যাঁ, একটি শ্রেণি ফাইল তৈরি করা হবে।

1 এবং 3 একই ধরণের প্রশ্ন। আপনি একটি স্থানীয় শ্রেণি ব্যবহার করবেন যেখানে আপনাকে কখনই কোনও তাত্ক্ষণিক বা কোনও পদ্ধতিতে প্রয়োগের বিশদ সম্পর্কে জানতে হবে না।

একটি সাধারণ ব্যবহার হ'ল কিছু ইন্টারফেসের একটি ফেলে দেওয়া বাস্তবায়ন তৈরি করা। উদাহরণস্বরূপ আপনি প্রায়শই এরকম কিছু দেখতে পাবেন:

  //within some method
  taskExecutor.execute( new Runnable() {
       public void run() {
            classWithMethodToFire.doSomething( parameter );
       }
  }); 

আপনার যদি এগুলির একটি গুচ্ছ তৈরি করতে এবং সেগুলির সাথে কিছু করার প্রয়োজন হয় তবে আপনি এটি এতে পরিবর্তন করতে পারেন

  //within some method
  class myFirstRunnableClass implements Runnable {
       public void run() {
            classWithMethodToFire.doSomething( parameter );
       }
  }
  class mySecondRunnableClass implements Runnable {
       public void run() {
            classWithMethodToFire.doSomethingElse( parameter );
       }
  }
  taskExecutor.execute(new myFirstRunnableClass());
  taskExecutor.execute(new mySecondRunnableClass());

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


জাভা স্থানীয় ক্লাসের কোন সংস্করণে কোন ধারণা চালু হয়েছে?
টানা স্লেজগাড়ির

1
জাভা ১.১ এ অভ্যন্তরীণ ক্লাস যুক্ত হয়েছিল - আমি অনুমান করছি স্থানীয় ক্লাসগুলিও ছিল তবে সে বিষয়ে আমার কাছে কোনও ডকুমেন্টেশন নেই।
জ্যাকব ম্যাটিসন

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

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

1
ওপি'র জন্য: নোট করুন যে স্থানীয় বর্গ থ্রেডগুলিতে যোগাযোগের জন্য একটি উপায় সরবরাহ করে - parameterউপরেরটি বদ্ধ পদ্ধতিতে ঘোষিত হতে পারে এবং উভয় থ্রেড দ্বারা অ্যাক্সেসযোগ্য।
ফ্লো 2 কে

15

এগুলিকে স্থানীয় ক্লাস বলা হয় । আপনি এখানে একটি বিশদ ব্যাখ্যা এবং একটি উদাহরণ খুঁজে পেতে পারেন । উদাহরণটি একটি নির্দিষ্ট বাস্তবায়ন দেয় যা পদ্ধতির বাইরের সম্পর্কে আমাদের জানার দরকার নেই।


2
দুর্দান্ত লিঙ্ক (এখনও 7+ বছর পরে কাজ করে!)। বিশেষত দ্রষ্টব্য, "সদস্য শ্রেণীর মতো, স্থানীয় ক্লাসগুলি একটি সমন্বিত দৃষ্টান্তের সাথে সম্পর্কিত এবং এতে থাকা শ্রেণীর ব্যক্তিগত সদস্যরা সহ যে কোনও সদস্য অ্যাক্সেস করতে পারবেন ।"
ফ্লো 2 কে

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

  2. আমি আসলে ভেবেছিলাম: "এ জাতীয় কোনও ফাইল লেখা হবে না।" যতক্ষণ না আমি কেবল এটি চেষ্টা করেছি: ওহ হ্যাঁ, এই জাতীয় ফাইল তৈরি করা হয়েছে! একে A $ 1B.class এর মতো কিছু বলা হবে, যেখানে A বহিরাগত শ্রেণি, এবং B স্থানীয় শ্রেণি।

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


2
২. এহরাম, নিশ্চয়ই এটি হবে। আপনার জাভা ফাইলে প্রতিটি নেস্টেড, স্থানীয় বা বেনাম শ্রেণীর জন্য ক্লাস ফাইলগুলি তৈরি করা হবে।
sepp2k

2
"২। এ জাতীয় কোনও ফাইল লেখা হবে না।" -- এটা ভুল. এটি তৈরি করে TestClass$1TestMethodClass.class, কীভাবে অভ্যন্তরীণ ক্লাসগুলির .classফাইলগুলির নামকরণ করা যায় তার সাদৃশ্য।
বহুবিশ্লেষকারীরা

উত্তম উত্তর, 2 এর ব্যাতিক্রম: আপনি বেনামে বর্গ তৈরি করতে পারবেন, এই ক্ষেত্রে "টেস্টক্লাস $ 1 টেস্টমেথডক্লাস.ক্লাস"
স্টিভ বি।

হ্যা, আমি দুঃখিত! আমি কয়েক সেকেন্ড আগে পর্যন্ত এটি বুঝতে পারি নি। আপনি বেঁচে থাকুন এবং শিখুন :-))
ক্রিস লারচার

বেনামে এবং স্থানীয় শ্রেণীর মধ্যে পার্থক্যটি হাইলাইট করার জন্য আমার +1 পেয়েছেন: কনস্ট্রাক্টর সংজ্ঞায়িত করতে।
ম্যাথিউইউ

7

এর আসল উদ্দেশ্য হ'ল আমাদের মধ্যে যারা ফাংশনাল ভাষায় লিখছেন যে ভান করতে চান তাদের সান্ত্বনা দেওয়ার জন্য ফাংশন কলগুলিতে ইনলাইন ক্লাস তৈরি করার অনুমতি দেওয়া;)


4

কেবলমাত্র যখন আপনি সম্পূর্ণ বিকাশযুক্ত ফাংশন অভ্যন্তরীণ বনাম বনাম বেনাম ক্লাস করতে চান (কেবল জাভা ক্লোজার) যখন নিম্নলিখিত শর্তগুলি পূরণ করা হয়

  1. আপনার একটি ইন্টারফেস সরবরাহ করতে হবে বা বিমূর্ত শ্রেণির প্রয়োগকরণ
  2. আপনি কলিং ফাংশনে সংজ্ঞায়িত কিছু চূড়ান্ত পরামিতি ব্যবহার করতে চান
  3. আপনাকে ইন্টারফেস কলটি কার্যকর করার কিছু স্থিতি রেকর্ড করতে হবে।

উদাহরণস্বরূপ, কেউ একজন চায় Runnableএবং আপনি যখন সম্পাদন শুরু এবং শেষ হয় আপনি রেকর্ড করতে চান।

বেনাম শ্রেণীর সাহায্যে এটি করা সম্ভব নয়, অভ্যন্তর শ্রেণীর সাথে আপনি এটি করতে পারেন।

এখানে আমার উদাহরণটি প্রদর্শন করার উদাহরণ রয়েছে

private static void testMethod (
        final Object param1,
        final Object param2
    )
{
    class RunnableWithStartAndEnd extends Runnable{
        Date start;
        Date end;

        public void run () {
            start = new Date( );
            try
            {
                evalParam1( param1 );
                evalParam2( param2 );
                ...
            }
            finally
            {
                end = new Date( );
            }
        }
    }

    final RunnableWithStartAndEnd runnable = new RunnableWithStartAndEnd( );

    final Thread thread = new Thread( runnable );
    thread.start( );
    thread.join( );

    System.out.println( runnable.start );
    System.out.println( runnable.end );
}

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


ফাংশন থেকে রিটার্ন মানগুলি নির্ধারণ করতে আমি # 2 কে কিছুটা আপত্তি করি।
এডি বি

2

অভ্যন্তরীণ ক্লাসগুলি সংজ্ঞায়িত করার প্রধান কারণ (কোনও পদ্ধতি বা শ্রেণীর মধ্যে) সদস্যদের অ্যাক্সেসিবিলিটি এবং ঘের বদ্ধ শ্রেণি এবং পদ্ধতির ভেরিয়েবলগুলি নিয়ে কাজ করা। একটি অভ্যন্তর শ্রেণি ব্যক্তিগত ডেটা সদস্যদের সন্ধান করতে পারে এবং সেগুলি পরিচালনা করতে পারে। যদি কোনও পদ্ধতির মধ্যে এটি চূড়ান্ত স্থানীয় পরিবর্তনশীলও মোকাবেলা করতে পারে।

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


1

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

ধরুন আপনার কাছে এই জাতীয় কোড রয়েছে:

JdbcTemplate jdbcOperations = new JdbcTemplate(this.myDataSource);
jdbcOperations.execute("call my_stored_procedure()")
jdbcOperations.query(queryToRun, new MyCustomRowMapper(), withInputParams);
jdbcOperations.update(queryToRun, withInputParams);

আসুন প্রথমে নির্বাহ () এর বাস্তবায়নটি দেখুন:

    @Override
    public void execute(final String sql) throws DataAccessException {
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL statement [" + sql + "]");
        }

        /**
         * Callback to execute the statement.
         (can access method local state like sql input parameter)
         */
        class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
            @Override
            @Nullable
            public Object doInStatement(Statement stmt) throws SQLException {
                stmt.execute(sql);
                return null;
            }
            @Override
            public String getSql() {
                return sql;
            }
        }

        //transforms method input into a functional Object
        execute(new ExecuteStatementCallback());
    }

শেষ লাইন নোট করুন। বাকী পদ্ধতিগুলির জন্য স্প্রিংও ঠিক এই "কৌশল" করে:

//uses local class QueryStatementCallback implements StatementCallback<T>, SqlProvider
jdbcOperations.query(...) 
//uses local class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider
jdbcOperations.update(...)

স্থানীয় ক্লাসগুলির সাথে "কৌতুক" কাঠামোটি একক পদ্ধতিতে those সমস্ত শ্রেণীর দৃশ্যের সাথে ডিল করার অনুমতি দেয় যা স্টেটমেন্টক্যালব্যাক ইন্টারফেসের মাধ্যমে এই শ্রেণিগুলি গ্রহণ করে। এই একক পদ্ধতিটি তাদের চারপাশে অ্যাকশন (এক্সিকিউট, আপডেট) এবং সাধারণ ক্রিয়াকলাপগুলির মধ্যে একটি সেতু হিসাবে কাজ করে (যেমন এক্সিকিউশন, সংযোগ পরিচালনা, ত্রুটি অনুবাদ এবং ডিবিএমএস কনসোল আউটপুট)

public <T> T execute(StatementCallback<T> action) throws DataAccessException    {
        Assert.notNull(action, "Callback object must not be null");

        Connection con = DataSourceUtils.getConnection(obtainDataSource());
        Statement stmt = null;
        try {
            stmt = con.createStatement();
            applyStatementSettings(stmt);
            //
            T result = action.doInStatement(stmt);
            handleWarnings(stmt);
            return result;
        }
        catch (SQLException ex) {
            // Release Connection early, to avoid potential connection pool deadlock
            // in the case when the exception translator hasn't been initialized yet.
            String sql = getSql(action);
            JdbcUtils.closeStatement(stmt);
            stmt = null;
            DataSourceUtils.releaseConnection(con, getDataSource());
            con = null;
            throw translateException("StatementCallback", sql, ex);
        }
        finally {
            JdbcUtils.closeStatement(stmt);
            DataSourceUtils.releaseConnection(con, getDataSource());
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.