একটি সুইচ বিবৃতিতে উদাহরণস্বরূপ অপারেটরটি ব্যবহার করা সম্ভব?


267

আমার কাছে instanceofঅবজেক্টের জন্য সুইচ কেস ব্যবহার করার একটি প্রশ্ন রয়েছে :

উদাহরণস্বরূপ: আমার সমস্যাটি জাভাতে পুনরুত্পাদন করা যেতে পারে:

if(this instanceof A)
    doA();
else if(this instanceof B)
    doB();
else if(this instanceof C)
    doC():

কীভাবে এটি ব্যবহার করে বাস্তবায়ন করা হবে switch...case?


6
যদি আপনি সত্যিই মনে করেন যে আপনার কোনও সুইচের দরকার আছে আপনি ক্লাসের নামটি হিস্ট করতে পারেন এবং এটি ব্যবহার করতে পারেন, তবে সম্ভাব্য সংঘর্ষের দিকে নজর রাখুন। উত্তরের পরিবর্তে মন্তব্য হিসাবে যুক্ত করা কারণ এটির ধারণাটি আমি আসলে ব্যবহার করি না। সম্ভবত আপনার যা প্রয়োজন তা ভিজিটর প্যাটার্ন।
ভিকির্ক

1
জাভা of-তে আপনি যেমন ভিকির্ক দেখিয়েছিলেন তেমন হ্যাশ সংঘর্ষ এড়াতে পুরোপুরি যোগ্য শ্রেণীর নামটিও স্যুইচ করতে পারেন তবে এটি এখনও কুৎসিত।
মিটজা

উত্তর:


225

এটি একটি সাধারণ দৃশ্য যেখানে সাব টাইপ পলিমারফিজম সাহায্য করে। নিম্নলিখিত করুন

interface I {
  void do();
}

class A implements I { void do() { doA() } ... }
class B implements I { void do() { doB() } ... }
class C implements I { void do() { doC() } ... }

তারপর আপনি কেবল কল করতে পারেন do()উপর this

আপনি পরিবর্তন করতে বিনামূল্যে না হন, তাহলে A, Bএবং C, আপনি একই অর্জনে পরিদর্শক প্যাটার্ন প্রয়োগ হতে পারে।


33
ভিজিটর প্যাটার্নটির অর্থ হ'ল এ, বি এবং সি একটি বিমূর্ত পদ্ধতি সহ একটি ইন্টারফেস প্রয়োগ করতে হবে যা কোনও ভিজিটরকে ইনপুট প্যারামিটার হিসাবে গ্রহণ করে, আপনি যদি এ, বি, সি পরিবর্তন করতে না পারেন এবং এর মধ্যে কোনওটিই সেই ইন্টারফেস প্রয়োগ করে না?
থার্মজ

21
দর্শকের ধরণ সম্পর্কে সর্বশেষ মন্তব্যটি ভুল। আপনার এখনও এ, বি এবং সি একটি ইন্টারফেস প্রয়োগ করতে হবে।
বেন থারলি

10
দুঃখজনকভাবে এটি কাজ করে না যদি () - কোডের জন্য হোস্টের পরিবেশ প্রয়োজন (যেমন ডায় () নিজেই উপস্থিত নয় এমন ভেরিয়েবলের অ্যাক্সেস)।
মাফু

2
@ মাফু ওপির প্রশ্নটি টাইপ ভিত্তিক প্রেরণের বিষয়ে ছিল। আপনার সমস্যাটির তুলনায় আপনার করার () পদ্ধতিটি প্রেরণের জন্য যদি আরও ইনপুট দরকার হয় তবে এখানে আলোচিত প্রশ্নের ক্ষেত্রের বাইরে IMHO।
jmg

3
এই উত্তরটি ধরে নেওয়া হয়েছে যে আপনি A, B, C ক্লাসগুলি সংশোধন করতে পারবেন, যদিও আমার ধারণা বিন্দুটি এ, বি, সি পরিবর্তন না করে এটি কীভাবে করা যায় কারণ তারা তৃতীয় অংশের লাইব্রেরিতে থাকতে পারে
মেঘলা_উথার

96

আপনি যদি কোনও ইন্টারফেসে একেবারে কোড করতে না পারেন, তবে আপনি একটি মধ্যস্থতাকারী হিসাবে একটি এনাম ব্যবহার করতে পারেন:

public A() {

    CLAZZ z = CLAZZ.valueOf(this.getClass().getSimpleName());
    switch (z) {
    case A:
        doA();
        break;
    case B:
        doB();
        break;
    case C:
        doC();
        break;
    }
}


enum CLAZZ {
    A,B,C;

}

তবে, আমাকে কিছু পরিবর্তন করতে হয়েছিল: 1) ক্লাসের রেফারেন্সের মাধ্যমে প্রতিটি এনাম আইডি শুরু করা; 2) এনাম আইডি। টু স্ট্রিং () সহ শ্রেণীর সাধারণ নামটি জোড় করান; 3) এনএম আইডি প্রতি সঞ্চিত শ্রেণীর রেফারেন্সের মাধ্যমে এনামটি সন্ধান করুন। আমি মনে করি এটি তখন নিখরচায় নিরাপদ।
অ্যাকোরিয়াস পাওয়ার

যদি এই। স্যুইচ
তেত্রি

40

কেবলমাত্র একটি মানচিত্র তৈরি করুন যেখানে ক্লাসটি কী এবং কার্যকারিতা, যেমন ল্যাম্বদা বা অনুরূপ, এর মান।

Map<Class,Runnable> doByClass = new HashMap<>();
doByClass.put(Foo.class, () -> doAClosure(this));
doByClass.put(Bar.class, this::doBMethod);
doByClass.put(Baz.class, new MyCRunnable());

// অবশ্যই, এটি একবারে আরম্ভ করার জন্য রিফ্যাক্টর

doByClass.get(getClass()).run();

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


3
সেরা সমাধান ইমো, বিশেষত কারণ এটি সহজে পুনর্নির্মাণের অনুমতি দেয়।
Feiteira

2
এই সমাধানের একমাত্র ক্ষতিটি হ'ল এটি ল্যাম্বডাসে স্থানীয় (পদ্ধতি) ভেরিয়েবলগুলি ব্যবহার করতে পারে না (ধরে নিই যে এটি অবশ্যই প্রয়োজন হতে পারে)।
জাপাটারো

1
@ জ্যাপাটারো আপনি রান্নেবলের পরিবর্তে ফাংশনে পরিবর্তন করতে পারেন, প্যারামিটার হিসাবে উদাহরণটি পাস করতে পারেন, প্রয়োজনে এটি নিক্ষেপ করুন
নভেটেরটা

সম্মত; এটি সেই কয়েকটি জবাবগুলির মধ্যে একটি যা আসলে ওপিকে যা বলছে তা করতে সহায়তা করে (এবং হ্যাঁ, কোডটি না করার জন্য প্রায়শই এটি রিফ্যাক্টর করা সম্ভব হয় instanceofএবং না, আমার পরিস্থিতি দুর্ভাগ্যক্রমে খুব সহজে সেগুলির মধ্যে একটি নয়) সেই বাক্সটি ...)
লন্ডবার্গ

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

36

যদি কেউ এটি পড়েন তবে:

জাভার সেরা সমাধানটি হ'ল:

public enum Action { 
    a{
        void doAction(...){
            // some code
        }

    }, 
    b{
        void doAction(...){
            // some code
        }

    }, 
    c{
        void doAction(...){
            // some code
        }

    };

    abstract void doAction (...);
}

এই ধরণের গ্রেট সুবিধাগুলি হ'ল:

  1. আপনি কেবল এটির মতো করুন (কোনও কিছুই স্যুইচ করে না):

    void someFunction ( Action action ) {
        action.doAction(...);   
    }
  2. যদি আপনি "d" নামে নতুন অ্যাকশন যুক্ত করেন তবে আপনাকে doAction (...) পদ্ধতিটি আবশ্যক

দ্রষ্টব্য: এই প্যাটার্নটি জোশুয়ার ব্লচে "কার্যকর জাভা (দ্বিতীয় সংস্করণ)" তে বর্ণিত হয়েছে


1
চমৎকার! @Overrideপ্রতিটি বাস্তবায়নের উপরে কি প্রয়োজনীয় doAction()?
mateuscb

9
এটি কীভাবে "সেরা" সমাধান? কোনটি actionব্যবহার করবেন তা আপনি কীভাবে সিদ্ধান্ত নেবেন ? একটি বাহ্যিক উদাহরণস্বরূপ - ক্যাসকেড যা someFunction()সঠিক সাথে কল করে action? এটি কেবল নির্দেশের অন্য স্তর যুক্ত করে।
পিওরস্পাইডার

1
না, এটি রানটাইমে স্বয়ংক্রিয়ভাবে সম্পন্ন হবে। আপনি যদি কিছু ফাংশন (অ্যাকশন.এ) কল করেন তবে a.doAction বলা হবে।
se.solovyev

11
আমি এটা বুঝতে পারি না। আপনি কীভাবে জানতে পারবেন কোন এনাম ব্যবহার করবেন? @ পিওরস্পাইডার যেমন বলেছিলেন, এটি করা ঠিক অন্য স্তরের কাজ বলে মনে হচ্ছে।
জেমস মানেস

2
এটি অত্যন্ত দুঃখের বিষয় যে আপনি একটি নিখুঁত উদাহরণ উপস্থাপন করেন নি , যেমন কীভাবে কোনও এন, বি বা সি এর কোনও ক্লাস-ইনস্ট্যান্স ম্যাপ করে। আমি এই এনামের কাছে ইনস্ট্যান্ট দেওয়ার চেষ্টা করব।
টম

21

আপনি পারবেন না। switchবিবৃতি শুধুমাত্র ধারণ করতে পারে caseবিবৃতি যা কম্পাইল সময় ধ্রুবক হয় এবং যা একটি পূর্ণসংখ্যা (আপ জাভা 6 এবং জাভা 7 একটি স্ট্রিং) এর নির্ণয় করা।

আপনি যা সন্ধান করছেন এটি ফাংশনাল প্রোগ্রামিংয়ে "প্যাটার্ন ম্যাচিং" বলে।

জাভাতে উদাহরণ এড়ানোও দেখুন


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

অবশ্যই, তবে কনস্ট্রাক্টরদের বিরুদ্ধে চেক করা উপরে বর্ণিত দৃশ্যের "সমতুল্য" হবে।
কার্লো ভি। ড্যাঙ্গো

1
কিছু ক্ষেত্রে, তবে সাধারণভাবে হয় না।
জেএমজি

সুইচগুলি এনামগুলিকেও সমর্থন করতে পারে।
সলোমন উকো

"আপনি পারবেন না" একটি ভিন্ন ভাষার দিকে নজর দেওয়া খুব কমই একটি সহায়ক উত্তর।
এল ব্ল্যাঙ্ক

17

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

জাভা 8 দিয়ে শুরু করে, আমরা ল্যাম্বডাস এবং জেনেরিকগুলি ব্যবহার করতে পারি এমন কিছু ফাংশনাল প্রোগ্রামারগুলির সাথে: যা প্যাটার্ন ম্যাচিংয়ের সাথে খুব পরিচিত give এটি মূল ভাষার বৈশিষ্ট্য নয় তবে জাভাসলং লাইব্রেরি একটি বাস্তবায়ন সরবরাহ করে। জাভাডোক থেকে উদাহরণ :

Match.ofType(Number.class)
    .caze((Integer i) -> i)
    .caze((String s) -> new BigDecimal(s))
    .orElse(() -> -1)
    .apply(1.0d); // result: -1

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


9

আমি জানি এটি খুব দেরী তবে ভবিষ্যতের পাঠকদের জন্য ...

উপরের পন্থাগুলি থেকে সাবধান থাকুন যা কেবলমাত্র , বি , সি শ্রেণীর নামের উপর ভিত্তি করে ...:

আপনি যদি গ্যারান্টি দিতে না পারেন যে , বি , সি ... ( বেসের সমস্ত সাবক্লাস বা প্রয়োগকারী ) চূড়ান্ত হয় তবে , বি , সি ... এর সাবক্লাসগুলি মোকাবেলা করা হবে না।

যদিও প্রচুর সাবক্লাস / প্রয়োগকারী সংস্থাগুলির জন্য যদি, অন্য, অন্য, আইফোনটি ধীর হয় তবে এটি আরও সঠিক।


তোমরা তো polymorphimsm ব্যবহার না করা উচিত (ওরফে গলি)
Val,

8

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

public enum MyEnum {
   A(A.class.getName()), 
   B(B.class.getName()),
   C(C.class.getName());

private String refClassname;
private static final Map<String, MyEnum> ENUM_MAP;

MyEnum (String refClassname) {
    this.refClassname = refClassname;
}

static {
    Map<String, MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
    for (MyEnum instance : MyEnum.values()) {
        map.put(instance.refClassname, instance);
    }
    ENUM_MAP = Collections.unmodifiableMap(map);
}

public static MyEnum get(String name) {
    return ENUM_MAP.get(name);
 }
}

এর সাথে এই জাতীয় সুইচ স্টেটমেন্ট ব্যবহার করা সম্ভব

MyEnum type = MyEnum.get(clazz.getName());
switch (type) {
case A:
    ... // it's A class
case B:
    ... // it's B class
case C:
    ... // it's C class
}

আমি বিশ্বাস করি যে যতক্ষণ পর্যন্ত JEP ইস্যু 8213076 পুরোপুরি বাস্তবায়িত হয় না ততক্ষণ পর্যন্ত লক্ষ্য শ্রেণীর পরিবর্তন না করে ধরণের উপর ভিত্তি করে একটি স্যুইচ স্টেটমেন্ট পাওয়াটাই সবচেয়ে পরিষ্কার উপায়।
রিক স্কাফ


5

এই জাতীয় সুইচ স্টেটমেন্ট ব্যবহার করা অবজেক্ট অরিয়েন্টেড উপায় নয়। পরিবর্তে পলিমারফিজমের শক্তিটি ব্যবহার করা উচিত । সহজভাবে লিখুন

this.do()

পূর্বে একটি বেস ক্লাস স্থাপন করা:

abstract class Base {
   abstract void do();
   ...
}

যা বেস ক্লাস A, Bএবং C:

class A extends Base {
    void do() { this.doA() }
}

class B extends Base {
    void do() { this.doB() }
}

class C extends Base {
    void do() { this.doC() }
}

@jmg suggeests ( stackoverflow.com/questions/5579309/switch-instanceof/... ) একজন ইন্টারফেস পরিবর্তে একটি বিমূর্ত বেস বর্গ ব্যবহার করে। কিছু সার্কসমেটেন্সে এটি সর্বোত্তম হতে পারে।
রায়েডওয়াল্ড

5

এটি দ্রুত কাজ করবে এবং ক্ষেত্রে সংবেদন তৈরি করবে
- আপনার তুলনামূলকভাবে অনেকগুলি 'কেস' রয়েছে
- কার্য সম্পাদন সংবেদনশীল প্রসঙ্গে প্রক্রিয়াটি কার্যকর করা হয়

public <T> T process(Object model) {
    switch (model.getClass().getSimpleName()) {
        case "Trade":
            return processTrade();
        case "InsuranceTransaction":
            return processInsuranceTransaction();
        case "CashTransaction":
            return processCashTransaction();
        case "CardTransaction":
            return processCardTransaction();
        case "TransferTransaction":
            return processTransferTransaction();
        case "ClientAccount":
            return processAccount();
        ...
        default:
            throw new IllegalArgumentException(model.getClass().getSimpleName());
    }
}

1
এটি উদাহরণস্বরূপ করার মতো নয়, কারণ এটি কেবলমাত্র কার্যকর হয় যদি প্রয়োগকারী ক্লাসটি স্যুইচ করতে ব্যবহৃত হয় তবে এটি ইন্টারফেস / অ্যাবস্ট্রাক্ট
ক্লাস

হ্যাঁ, এটি নয়
মাইক

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

4

আপনি স্যুইচটি কেবল বাইট, শর্ট, চর, ইনট, স্ট্রিং এবং এনুমারেটেড প্রকারের সাথে কাজ করতে পারবেন না (এবং আদিমগুলির অবজেক্ট সংস্করণগুলিও এটি আপনার জাভা সংস্করণের উপর নির্ভর করে, স্ট্রিংস switchজাভা 7 এ এডিট করা যেতে পারে )


আপনি জাভা St এর স্ট্রিংগুলিতে স্যুইচ করতে পারবেন না এবং আপনি "আদিমগুলির অবজেক্ট সংস্করণগুলি" স্যুইচ করতে পারবেন না।
লুকাশ এদার

@ বোজো আমি বলেছিলাম এটি আপনার জাভা সংস্করণের উপর নির্ভর করে, জাভা 7-এ আপনি স্ট্রিংস স্যুইচ করতে পারেন।
টেনেম

@ লুকাস এদার আপনার জাভা স্পেসটি যাচাই করতে পারেন তা পরীক্ষা করুন
টেনেম

4

আমি ব্যক্তিগতভাবে নিম্নলিখিত জাভা 1.8 কোড পছন্দ করি:

    mySwitch("YY")
            .myCase("AA", (o) -> {
                System.out.println(o+"aa");
            })
            .myCase("BB", (o) -> {
                System.out.println(o+"bb");
            })
            .myCase("YY", (o) -> {
                System.out.println(o+"yy");
            })
            .myCase("ZZ", (o) -> {
                System.out.println(o+"zz");
            });

আউটপুট দেবে:

YYyy

নমুনা কোড স্ট্রিং ব্যবহার করে তবে আপনি ক্লাস সহ যে কোনও অবজেক্টের ধরণ ব্যবহার করতে পারেন। যেমন.myCase(this.getClass(), (o) -> ...

নিম্নলিখিত স্নিপেট প্রয়োজন:

public Case mySwitch(Object reference) {
    return new Case(reference);
}

public class Case {

    private Object reference;

    public Case(Object reference) {
        this.reference = reference;
    }

    public Case myCase(Object b, OnMatchDo task) {
        if (reference.equals(b)) {
            task.task(reference);
        }
        return this;
    }
}

public interface OnMatchDo {

    public void task(Object o);
}

4

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

String formatted;
switch (obj) {
    case Integer i: formatted = String.format("int %d", i); break;
    case Byte b:    formatted = String.format("byte %d", b); break;
    case Long l:    formatted = String.format("long %d", l); break;
    case Double d:  formatted = String.format("double %f", d); break;
    case String s:  formatted = String.format("String %s", s); break
    default:        formatted = obj.toString();
}  

বা তাদের ল্যাম্বদা সিনট্যাক্স ব্যবহার করে এবং একটি মান ফেরত

String formatted = 
    switch (obj) {
        case Integer i -> String.format("int %d", i)
        case Byte b    -> String.format("byte %d", b);
        case Long l    -> String.format("long %d", l); 
        case Double d  -> String.format("double %f", d); 
        case String s  -> String.format("String %s", s); 
        default        -> obj.toString();
    };

যে কোনও উপায়ে তারা সুইচগুলি দিয়ে দুর্দান্ত জিনিস করছে।


3

আপনি যদি সাধারণ ইন্টারফেসটি পরিচালনা করতে পারেন তবে আপনি একটি এনামে যুক্ত করতে পারেন এবং প্রতিটি শ্রেণীর একটি অনন্য মূল্য ফেরত পেতে পারেন। আপনার উদাহরণ বা দর্শনার্থীর প্যাটার্নের প্রয়োজন হবে না।

আমার জন্য, যুক্তিটি সুইচ স্টেটমেন্টে লিখিত হওয়া দরকার, বস্তু নিজেই নয়। এটি আমার সমাধান ছিল:

ClassA, ClassB, and ClassC implement CommonClass

ইন্টারফেস:

public interface CommonClass {
   MyEnum getEnumType();
}

Enum:

public enum MyEnum {
  ClassA(0), ClassB(1), ClassC(2);

  private int value;

  private MyEnum(final int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }

Impl:

...
  switch(obj.getEnumType())
  {
    case MyEnum.ClassA:
      ClassA classA = (ClassA) obj;
    break;

    case MyEnum.ClassB:
      ClassB classB = (ClassB) obj;
    break;

    case MyEnum.ClassC:
      ClassC classC = (ClassC) obj;
    break;
  }
...

আপনি জাভা 7 এ থাকলে আপনি এনামের জন্য স্ট্রিং মান রাখতে পারেন এবং স্যুইচ কেস ব্লকটি এখনও কাজ করবে।


valueআপনি ধ্রুবক সরাসরি ব্যবহার করতে পারেন (যেমন আপনাকে যা করতে) - ক্ষেত্র অপ্রয়োজনীয় আপনি শুধুমাত্র enum ধ্রুবক পার্থক্য করতে চাই।
ব্যবহারকারী 905686

2

এ কেমন?

switch (this.name) 
{
  case "A":
    doA();
    break;
  case "B":
    doB();
    break;
  case "C":
    doC();
    break;
  default:
    console.log('Undefined instance');
}

3
আউট নির্দেশ করা উচিত যে এই জাভা 7. শুধুমাত্র কাজ করে এবং যে আপনার ফোন করতে হবে this.getSimpleName()যদি পোস্টার (হাঁ, তিনি কনসোল, Hehe ব্যবহার করছে) জাতীয় সঙ্গে গুলিয়ে ফেলা হয় নিশ্চিত না।
পাব্লিসকো

5
এটি উত্স কোড রেফারেনশিয়াল স্বচ্ছতার বাইরে যাওয়ার সমস্যা আছে। অর্থাৎ, আপনার আইডিই রেফারেন্স অখণ্ডতা অর্জন করতে সক্ষম হবে না। মনে করুন আপনি নিজের নামটি পরিবর্তন করতে চান। প্রতিফলন মন্দ।
Val,

1
দুর্দান্ত ধারণা নয় Not আপনার একাধিক ক্লাস লোডার থাকলে শ্রেণীর নামগুলি অনন্য নয়।
দোরাদাস

কোড কম্প্রেশন (to প্রোগুয়ার্ড) এর কথা ভাঙ্গলে
ম্যাথিয়াস

1

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

instance.getClass().getName();

ক্লাস বাস্তবায়ন নামের একটি স্ট্রিং প্রদান করে। যেমন: org.eclipse.emf.ecore.util.EcoreUtil

instance.getClass().getSimpleName();

সরল নিন্দা দেয় যেমন: EcoreUtil returns


আপনি এটির switchহিসাবে এটি ব্যবহার করতে পারবেন না caseকারণ এটি ধ্রুবক মান নয়
বি-গাংস্টেআর

1

আপনার যদি "এই" অবজেক্টের শ্রেণি ধরণের মাধ্যমে "স্যুইচ" করতে হয় তবে এই উত্তরটি সেরা https://stackoverflow.com/a/5579385/2078368

তবে আপনার যদি অন্য কোনও চলকটিতে "স্যুইচ" প্রয়োগ করতে হয়। আমি অন্য একটি সমাধান পরামর্শ দিতে হবে। নিম্নলিখিত ইন্টারফেস সংজ্ঞায়িত:

public interface ClassTypeInterface {
    public String getType();
}

আপনি "স্যুইচ" করতে চান এমন প্রতিটি শ্রেণিতে এই ইন্টারফেসটি প্রয়োগ করুন। উদাহরণ:

public class A extends Something implements ClassTypeInterface {

    public final static String TYPE = "A";

    @Override
    public String getType() {
        return TYPE;
    }
}

এর পরে আপনি এটি নিম্নলিখিত উপায়ে ব্যবহার করতে পারেন:

switch (var.getType()) {
    case A.TYPE: {
        break;
    }
    case B.TYPE: {
        break;
    }
    ...
}

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


স্ট্রিং এর জন্য ব্যবহারের পরিবর্তে TYPE, আপনি একটি এনাম ব্যবহার করতে পারেন এবং স্বতন্ত্রতার গ্যারান্টিযুক্ত (এটি এই উত্তর হিসাবে করা হয়েছে )। যাইহোক, যে কোনও পদ্ধতির সাথে আপনি যখন কোনও নাম পরিবর্তন করবেন তখন আপনাকে দুটি জায়গায় রিফ্যাক্টর করতে হবে।
ব্যবহারকারী 905686

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

আমার অর্থ ক্লাস এ এর ​​নামকরণের সাথে সাথে নাম পরিবর্তন করার সময় স্বয়ংক্রিয় রিফ্যাক্টরিং চলকটি অন্তর্ভুক্ত করতে পারে না TYPE = "A"। বিশেষত এটি সংশ্লিষ্ট বর্গের বাইরে থাকলে, ম্যানুয়ালি এটি করার সময় কেউ এটিকে ভুলে যেতে পারে। ইন্টেলিজ প্রকৃতপক্ষে স্ট্রিং বা মন্তব্যে শ্রেণীর নামের উপস্থিতিগুলি খুঁজে পায় তবে এটি কেবল একটি পাঠ্য অনুসন্ধান (সিনট্যাক্স গাছের পরিবর্তে দেখার পরিবর্তে) এবং এতে মিথ্যা ধনাত্মকতা রয়েছে।
ব্যবহারকারী 905686

@ ব্যবহারকারী 905686 ধারণাটি কল্পনা করার জন্য এটি কেবল একটি উদাহরণ। বাস্তব প্রকল্পে টাইপ সংজ্ঞাগুলির জন্য স্ট্রিং ব্যবহার করবেন না, কিছু মাইটাইপস শ্রেণীর ধারককে পূর্ণসংখ্যার ধ্রুবক (বা এনাম) হিসাবে ঘোষণা করুন এবং ক্লাসটাইপআইন্টারফেস প্রয়োগকারী ক্লাসগুলিতে তাদের ব্যবহার করুন।
সের্গেই ক্রিভেনভকভ

1

এখানে http://www.vavr.io/ ব্যবহার করে জাভা 8 এ এটি সম্পাদন করার কার্যকরী উপায়

import static io.vavr.API.*;
import static io.vavr.Predicates.instanceOf;
public Throwable liftRootCause(final Throwable throwable) {
        return Match(throwable).of(
                Case($(instanceOf(CompletionException.class)), Throwable::getCause),
                Case($(instanceOf(ExecutionException.class)), Throwable::getCause),
                Case($(), th -> th)
        );
    }

1

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

interface Processable {
    <R> R process(final Processor<R> processor);
}

interface Processor<R> {
    R process(final A a);
    R process(final B b);
    R process(final C c);
    // for each type of Processable
    ...
}

class A implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

class B implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

class C implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

তারপরে যেখানে যেখানে "স্যুইচ" দরকার হয় আপনি নীচে এটি করতে পারেন:

public class LogProcessor implements Processor<String> {
    private static final Logger log = Logger.for(LogProcessor.class);

    public void logIt(final Processable base) {
        log.info("Logging for type {}", process(base));
    }

    // Processor methods, these are basically the effective "case" statements
    String process(final A a) {
        return "Stringifying A";
    }

    String process(final B b) {
        return "Stringifying B";
    }

    String process(final C c) {
        return "Stringifying C";
    }
}

এই ভিজিটর প্যাটার্ন, যা ইতিমধ্যে এই উত্তর আলোচনা করা হয় মত অনেক দেখায় stackoverflow.com/a/5579385
typeracer

0

শ্রেণীর নাম সহ একটি এনাম তৈরি করুন ।

public enum ClassNameEnum {
    A, B, C
}

বস্তুর শ্রেণীর নামটি সন্ধান করুন । এনামের উপরে একটি সুইচ কেস লিখুন ।

private void switchByClassType(Object obj) {

        ClassNameEnum className = ClassNameEnum.valueOf(obj.getClass().getSimpleName());

        switch (className) {
            case A:
                doA();
                break;
            case B:
                doB();
                break;
            case C:
                doC();
                break;
        }
    }
}

আশাকরি এটা সাহায্য করবে.


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

0

এক্সিলিপ মডেলিং ফ্রেমওয়ার্কটির একটি আকর্ষণীয় ধারণা রয়েছে যা উত্তরাধিকারকেও বিবেচনা করে। স্যুইচ ইন্টারফেসে মূল ধারণাটি সংজ্ঞায়িত করা হয় : ডসউইচ পদ্ধতিটি চালু করে স্যুইচিং করা হয় ।

সত্যিই আকর্ষণীয় কি বাস্তবায়ন হয়। প্রতিটি ধরণের আগ্রহের জন্য, ক

public T caseXXXX(XXXX object);

পদ্ধতিটি অবশ্যই প্রয়োগ করা উচিত (একটি ডিফল্ট বাস্তবায়ন নাল ফেরার সাথে)। DoSwitch বাস্তবায়ন আল কল করার প্রচেষ্টা করা হবে caseXXX তার সব ধরনের অনুক্রমের জন্য বস্তুর উপর পদ্ধতি। এর লাইনে কিছু:

BaseType baseType = (BaseType)object;
T result = caseBaseType(eAttribute);
if (result == null) result = caseSuperType1(baseType);
if (result == null) result = caseSuperType2(baseType);
if (result == null) result = caseSuperType3(baseType);
if (result == null) result = caseSuperType4(baseType);
if (result == null) result = defaultCase(object);
return result;

আসল কাঠামো প্রতিটি শ্রেণীর জন্য একটি পূর্ণসংখ্যার আইডি ব্যবহার করে, সুতরাং যুক্তিটি আসলে খাঁটি স্যুইচ হয়:

public T doSwitch(Object object) {
    return doSwitch(object.class(), eObject);
}

protected T doSwitch(Class clazz, Object object) {
    return doSwitch(getClassifierID(clazz), object);
}

protected T doSwitch(int classifierID, Object theObject) {
    switch (classifierID) {
    case MyClasses.BASETYPE:
    {
      BaseType baseType = (BaseType)object;
      ...
      return result;
    }
    case MyClasses.TYPE1:
    {
      ...
    }
  ...

আরও ভাল ধারণা পেতে আপনি ECoreSwitch এর সম্পূর্ণ বাস্তবায়নটি দেখতে পারেন ।


-1

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

        DEFINE_TYPE:
        {
            if (a instanceof x){
                //do something
                break DEFINE_TYPE;
            }
            if (a instanceof y){
               //do something
                break DEFINE_TYPE;
            }
            if (a instanceof z){
                // do something
                break DEFINE_TYPE;
            }
        }

ওপি কর্তৃক প্রদত্ত if... else ifকোডের চেয়ে এটি কীভাবে ভাল ?
টাইপরেসার

শুধু আমার আগের মন্তব্যে সম্প্রসারিত কি তুমি প্রস্তাব প্রতিস্থাপন মূলত if... else if"এতে যান" বিবৃতি, যা দিয়ে ভুল জাভা মত ভাষায় নিয়ন্ত্রণ প্রবাহ বাস্তবায়ন উপায়।
টাইপরেসার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.