প্যারামিটারের আসল প্রকারের ভিত্তিতে ওভারলোড পদ্ধতি নির্বাচন


115

আমি এই কোডটি নিয়ে পরীক্ষা নিরীক্ষা করছি:

interface Callee {
    public void foo(Object o);
    public void foo(String s);
    public void foo(Integer i);
}

class CalleeImpl implements Callee
    public void foo(Object o) {
        logger.debug("foo(Object o)");
    }

    public void foo(String s) {
        logger.debug("foo(\"" + s + "\")");
    }

    public void foo(Integer i) {
        logger.debug("foo(" + i + ")");
    }
}

Callee callee = new CalleeImpl();

Object i = new Integer(12);
Object s = "foobar";
Object o = new Object();

callee.foo(i);
callee.foo(s);
callee.foo(o);

এটি foo(Object o)তিনবার প্রিন্ট করে । আমি আশা করি যে পদ্ধতি নির্বাচনটি বাস্তবের (ঘোষিত নয়) প্যারামিটার ধরণের বিবেচনায় নেবে। আমি কিছু অনুপস্থিত করছি? সেখানে যাতে এটি প্রিন্ট করব এই কোড পরিবর্তন করতে একটি উপায় আছে কি foo(12), foo("foobar")এবং foo(Object o)?

উত্তর:


96

আমি আশা করি যে পদ্ধতি নির্বাচনটি বাস্তবের (ঘোষিত নয়) প্যারামিটার ধরণের বিবেচনায় নেবে। আমি কিছু অনুপস্থিত করছি?

হ্যাঁ. আপনার প্রত্যাশা ভুল জাভাতে, ডায়নামিক মেথড প্রেরণ কেবলমাত্র যে বস্তুটির জন্য বলা হয় তার জন্য ঘটে, প্যারামিটার ধরণের ওভারলোডেড পদ্ধতির জন্য নয়।

Citing জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন :

যখন কোনও পদ্ধতিটি আহ্বান করা হয় (§15.12), আসল আর্গুমেন্টগুলির সংখ্যা (এবং কোনও সুস্পষ্ট ধরণের আর্গুমেন্ট) এবং সংকলনের সময় সংকলনের সময় বিভিন্ন ধরণের যুক্তি ব্যবহৃত হবে সেই পদ্ধতির স্বাক্ষর নির্ধারণ করার জন্য ( §15.12.2)। যদি যে পদ্ধতিটি আহ্বান করতে হয় তা যদি একটি উদাহরণ পদ্ধতি হয়, তবে ডাইনামিক পদ্ধতি অনুসন্ধান (§15.12.4) ব্যবহার করে, আসল পদ্ধতিটি রান সময়ে নির্ধারিত হবে।


4
আপনি যে উদ্ধৃতিটি উদ্ধৃত করেছেন তা দয়া করে ব্যাখ্যা করতে পারেন। দুটি বাক্য একে অপরের বিরোধিতা বলে মনে হচ্ছে। উপরের উদাহরণটিতে উদাহরণ পদ্ধতি ব্যবহার করা হয়েছে, তবুও পদ্ধতিটি আহ্বান করা স্পষ্টভাবে রান সময়ে নির্ধারিত হচ্ছে না।
অ্যালেক্স ওয়ার্ডেন 21

15
@ অ্যালেক্স ওয়ার্ডেন: এক্ষেত্রে যে পদ্ধতিটি বলা হবে তার স্বাক্ষর নির্ধারণের জন্য পদ্ধতির পরামিতিগুলির সংকলন সময়ের ধরণ ব্যবহৃত হয় foo(Object)। রানটাইমের সময়, অবজেক্টটির শ্রেণীর যে পদ্ধতিটি বলা হয় তা নির্ধারণ করে সেই পদ্ধতির কোন বাস্তবায়ন বলা হয় তা বিবেচনায় রেখে এটি ঘোষিত ধরণের উপক্লাসের উদাহরণ হতে পারে যা পদ্ধতিটিকে ওভাররাইড করে।
মাইকেল বর্গওয়ার্ট 21

86

যেমন পূর্বে উল্লিখিত হিসাবে সংকলন সময়ে ওভারলোডিং রেজোলিউশন সঞ্চালিত হয়।

জাভা পাজলারের কাছে এটির একটি দুর্দান্ত উদাহরণ রয়েছে:

ধাঁধা 46: বিভ্রান্তিকর নির্মাণকারীর কেস

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

public class Confusing {

    private Confusing(Object o) {
        System.out.println("Object");
    }

    private Confusing(double[] dArray) {
        System.out.println("double array");
    }

    public static void main(String[] args) {
        new Confusing(null);
    }
}

সমাধান 46: বিভ্রান্তিকর নির্মাণকারীর কেস

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

আমাদের প্রোগ্রামে, উভয় কনস্ট্রাক্টর অ্যাক্সেসযোগ্য এবং প্রযোজ্য। কনস্ট্রাক্টর কনফিউজিং (অবজেক্ট) কনফিউজিং (ডাবল []) তে পাস হওয়া কোনও প্যারামিটার গ্রহণ করে , সুতরাং কনফিউজিং (অবজেক্ট) কম নির্দিষ্ট নয়। (প্রতিটি ডাবল অ্যারে একটি বস্তু , তবে প্রতিটি বস্তু একটি ডাবল অ্যারে নয় )) সর্বাধিক সুনির্দিষ্ট নির্মাতা কনফিউজিং (ডাবল []) , যা প্রোগ্রামটির আউটপুট ব্যাখ্যা করে।

আপনি দ্বিগুণ টাইপের একটি মান পাস করলে এই আচরণটি বোধগম্য হয় ; এটা অনির্দিষ্ট অথবা যদি আপনি পাস হয় নালএই ধাঁধাটি বোঝার মূল চাবিকাঠিটি হল যে পদ্ধতি বা নির্মাণকারী সর্বাধিক নির্দিষ্ট সেই পরীক্ষায় প্রকৃত প্যারামিটারগুলি ব্যবহার করা হয় না : অনুরোধে উপস্থিত পরামিতিগুলি। কোন ওভারলোডিং প্রযোজ্য তা নির্ধারণ করতে এগুলি ব্যবহার করা হয়। একবার সংকলক কোন ওভারলোডিংগুলি প্রযোজ্য এবং অ্যাক্সেসযোগ্য তা নির্ধারণ করে, এটি কেবলমাত্র আনুষ্ঠানিক প্যারামিটারগুলি ব্যবহার করে: সর্বাধিক নির্দিষ্ট ওভারলোডিং নির্বাচন করে: ঘোষণায় উপস্থিত প্যারামিটারগুলি।

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


4
আমি আশা করি এটি বলার জন্য দেরি না করে - "এসওএফ-এর অন্যতম সেরা ব্যাখ্যা"। ধন্যবাদ :)
TheLostMind

5
আমি বিশ্বাস করি যে আমরা যদি নির্মাণকারীকে 'ব্যক্তিগত বিভ্রান্তি (int [] আইআরআই)' যোগ করি তবে এটি সংকলন করতে ব্যর্থ হয়, তাই না? কারণ এখন একই স্বাতন্ত্র্য সহ দুটি কনস্ট্রাক্টর রয়েছে।
রাইজার

যদি আমি ডায়নামিক রিটার্নের ধরণগুলি ফাংশন ইনপুট হিসাবে ব্যবহার করি তবে এটি সর্বদা কম সুনির্দিষ্ট ব্যবহার করে ... এমন পদ্ধতিটি বলেছিল যা সমস্ত সম্ভাব্য প্রত্যাবর্তনের মানগুলির জন্য ব্যবহার করা যেতে পারে ...
কায়সার

16

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

তবে, যেহেতু আপনি Integers এবং Strings এর সাথে ডিল করছেন , আপনি সহজেই এই প্যাটার্নটি অন্তর্ভুক্ত করতে পারবেন না (আপনি কেবল এই ক্লাসগুলি সংশোধন করতে পারবেন না)। সুতরাং, switchঅবজেক্ট রান- টাইমের একটি দৈত্য আপনার পছন্দসই অস্ত্র হবে।


11

জাভাতে কল করার পদ্ধতিটি (যে পদ্ধতিতে স্বাক্ষরটি ব্যবহার করতে হবে) সংকলনের সময় নির্ধারিত হয়, সুতরাং এটি সংকলনের সময় টাইপের সাথে যায়।

এই চারপাশে কাজ করার জন্য সাধারণ প্যাটার্নটি হ'ল অবজেক্টের স্বাক্ষর সহ পদ্ধতিতে অবজেক্টের ধরণটি পরীক্ষা করা এবং একটি কাস্টের সাহায্যে পদ্ধতিতে ডেলিগেট করা।

    public void foo(Object o) {
        if (o instanceof String) foo((String) o);
        if (o instanceof Integer) foo((Integer) o);
        logger.debug("foo(Object o)");
    }

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


4

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

আমি যে সমাধানটি ব্যবহার করেছি তা হ'ল প্রতিবিম্বের মাধ্যমে নির্মাণকারীর সন্ধান করা ...

public Parameter[] convertObjectsToParameters(Object[] objArray) {
    Parameter[] paramArray = new Parameter[objArray.length];
    int i = 0;
    for (Object obj : objArray) {
        try {
            Constructor<Parameter> cons = Parameter.class.getConstructor(obj.getClass());
            paramArray[i++] = cons.newInstance(obj);
        } catch (Exception e) {
            throw new IllegalArgumentException("This method can't handle objects of type: " + obj.getClass(), e);
        }
    }
    return paramArray;
}

কোনও কুৎসিত উদাহরণ, সুইচ স্টেটমেন্ট, বা দর্শনার্থীর প্যাটার্নের প্রয়োজন নেই! :)


2

কোন পদ্ধতিতে কল করতে হবে তা নির্ধারণ করার চেষ্টা করার সময় জাভা রেফারেন্সের ধরণটি দেখে। আপনি যদি নিজের কোডটি জোর করে চাপাতে চান তবে আপনি 'সঠিক' পদ্ধতিটি চয়ন করেন, আপনি নির্দিষ্ট ক্ষেত্রের উদাহরণ হিসাবে আপনার ক্ষেত্রগুলি ঘোষণা করতে পারেন:

Integeri = new Integer(12);
String s = "foobar";
Object o = new Object();

আপনি আপনার পরমগুলিকে পরমের ধরণ হিসাবে নিক্ষেপ করতে পারেন:

callee.foo(i);
callee.foo((String)s);
callee.foo(((Integer)o);

1

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

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