.Equals () উত্পন্ন করার সময় উদাহরণস্বরূপ getClass () পছন্দ করার কোনও কারণ?


174

আমি উত্পন্ন করতে .equals()এবং গ্রহণের জন্য Eclipse ব্যবহার করছি .hashCode()এবং "প্রকারের সাথে তুলনা করতে 'উদাহরণ ব্যবহার করুন' লেবেলযুক্ত একটি বিকল্প রয়েছে। ডিফল্টটি এই বিকল্পটি চেক করা না হওয়ার জন্য এবং .getClass()ধরণের তুলনা করার জন্য ব্যবহার করা হয়। আমার .getClass()বেশি পছন্দ করার কোনও কারণ আছে কি instanceof?

ব্যবহার না করে instanceof:

if (obj == null)
  return false;
if (getClass() != obj.getClass())
  return false;

ব্যবহার instanceof:

if (obj == null)
  return false;
if (!(obj instanceof MyClass))
  return false;

আমি সাধারণত instanceofবিকল্পটি পরীক্ষা করি এবং তারপরে প্রবেশ করে " if (obj == null)" চেকটি সরিয়ে ফেলি । (এটি অনর্থক যেহেতু নাল বস্তু সর্বদা ব্যর্থ হবে instanceof)) কোনও খারাপ ধারণা আছে এমন কোনও কারণ আছে কি?


1
এক্সপ্রেশনটি x instanceof SomeClassযদি মিথ্যা xহয় null। সুতরাং, দ্বিতীয় সিনট্যাক্সের নাল চেকের দরকার নেই।
আরডিএস

5
@ আরডিএস হ্যাঁ, কোড স্নিপেটের সাথে সাথেই অনুচ্ছেদটি এটিও বলেছে। এটি কোড স্নিপেটে রয়েছে কারণ এটিই গ্রহনটি উত্পন্ন করে।
কিপ করুন

উত্তর:


100

আপনি ব্যবহার করেন তাহলে instanceof, আপনার উপার্জন equalsবাস্তবায়ন finalপদ্ধতির প্রতিসাম্য চুক্তি নিশ্চয়ই নিরাপদে নিয়ে যাবেন x.equals(y) == y.equals(x)। যদি finalসীমাবদ্ধ মনে হয় তবে আপনার ওভাররাইডিং বাস্তবায়নগুলি Objectক্লাস দ্বারা প্রতিষ্ঠিত চুক্তিটি পুরোপুরি বজায় রেখেছে তা নিশ্চিত করার জন্য আপনার অবজেক্টের সমতুল্যতার ধারণাটি সাবধানতার সাথে পরীক্ষা করে দেখুন ।


আমি যখন জোশ ব্লচের উক্তিটি পড়েছিলাম তখন তা আমার মনে আসে। +1 :)
জোহানেস স্কাওব - লিটব

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

আমি এটিকে "যদি finalসীমাবদ্ধ মনে হয়" (উভয় equalsএবং উভয়ই hashCode) যুক্ত করে থাকি তবে চুক্তির প্রতিসাম্য এবং ট্রানজিটিভিটি প্রয়োজনীয়তা সংরক্ষণের getClass()পরিবর্তে সাম্যতা ব্যবহার করব । instanceofequals
শ্যাডো ম্যান

176

জোশ ব্লচ আপনার পদ্ধতির পক্ষে:

আমি instanceofপদ্ধতির পক্ষে যাওয়ার কারণটি হ'ল আপনি যখন getClassএপ্রোচটি ব্যবহার করেন তখন আপনার নিষেধাজ্ঞা থাকে যে অবজেক্টগুলি একই শ্রেণীর অন্যান্য বস্তুর সমান, একই রান টাইম টাইপের। যদি আপনি একটি শ্রেণি প্রসারিত করেন এবং এর সাথে বেশ কয়েকটি নিরীহ পদ্ধতি যুক্ত করেন, তবে সাবক্লাসের কিছু অবজেক্ট সুপার বর্গের কোনও বস্তুর সমান কিনা তা পরীক্ষা করে দেখুন, এমনকি সমস্ত গুরুত্বপূর্ণ দিকগুলিতে বস্তু সমান হলেও, আপনি পাবেন অবাক করা উত্তর যে তারা সমান নয়। প্রকৃতপক্ষে, এটি লিসকভ প্রতিস্থাপন নীতিটির একটি কঠোর ব্যাখ্যা লঙ্ঘন করে এবং খুব অবাক আচরণের দিকে নিয়ে যেতে পারে। জাভাতে, এটি বিশেষভাবে গুরুত্বপূর্ণ কারণ বেশিরভাগ সংগ্রহ (HashTable, ইত্যাদি) সমান পদ্ধতির উপর ভিত্তি করে। আপনি যদি সুপার ক্লাসের কোনও সদস্যকে কী হিসাবে একটি হ্যাশ টেবিলের মধ্যে রাখেন এবং তারপরে এটি একটি সাবক্লাস উদাহরণ ব্যবহার করে সন্ধান করেন তবে আপনি এটি পাবেন না কারণ তারা সমান নয়।

আরও দেখুন এই তাই উত্তর

কার্যকর জাভা অধ্যায় 3 এটিকেও অন্তর্ভুক্ত করে।


18
+1 জাভা করছে এমন প্রত্যেকেরই কমপক্ষে 10 বার বইটি পড়তে হবে!
আন্দ্রে

16
উদাহরণস্বরূপ পদ্ধতির সমস্যাটি হ'ল এটি অবজেক্ট.এক্কালস () এর "প্রতিসম" বৈশিষ্ট্যটি ভেঙে দেয় যে এটি সম্ভব হয়ে যায় যে x.equals (y) == সত্য তবে y.equals (x) == মিথ্যা যদি x.getClass হয় ()! = y.getClass ()। আমি একেবারে প্রয়োজনীয় না হলে (যেমন, পরিচালিত বা প্রক্সি সামগ্রীর জন্য ওভাররাইডিং সমান ()) না ভাঙ্গতে পছন্দ করি।
কেভিন সিতজে

8
উদাহরণস্বরূপ পদ্ধতির অবস্থানটি যথাযথ হয় যখন এবং কেবলমাত্র যখন বেস ক্লাসটি সাবক্লাস অবজেক্টগুলির মধ্যে সাম্যটির অর্থ কী হওয়া উচিত তা নির্ধারণ করে। ব্যবহার করা getClass, এলএসপি লঙ্ঘন করে না, যেহেতু এলএসপি কেবল বিদ্যমান উদাহরণগুলির সাথে কী করা যায় তার সাথে সম্পর্কিত - কোন ধরণের দৃষ্টান্ত তৈরি করা যায় না not যে ক্লাসটি ফিরিয়ে দিয়েছিল getClassতা হ'ল কোনও অবজেক্টের উদাহরণের অপরিবর্তনীয় সম্পত্তি। এলএসপি বোঝায় না যে একটি সাবক্লাস তৈরি করা সম্ভব হবে যেখানে সেই সম্পত্তিটি যেটি তৈরি করেছে, তা ছাড়া অন্য কোনও শ্রেণিকে নির্দেশ করে।
সুপারক্যাট

66

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

উপসংহার

সমান () এর বাস্তবায়নের চারটি নির্বিচারে নির্বাচিত উদাহরণগুলি পৃথকীকরণের পরে, আমরা কী উপসংহার করব?

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

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

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


61

ব্যবহারের কারণ getClassহ'ল equalsচুক্তির প্রতিসম বৈশিষ্ট্য নিশ্চিত করা । সমান জাভাডক্স থেকে:

এটি প্রতিসাম্য: যে কোনও অ-নাল রেফারেন্স মান x এবং y এর জন্য, x.equals (y) এর সত্য হওয়া উচিত এবং কেবল যদি y.equals (x) সত্য হয়।

উদাহরণস্বরূপ ব্যবহার করে, প্রতিসম না হওয়া সম্ভব। উদাহরণ বিবেচনা করুন: কুকুর প্রাণী প্রসারিত। অ্যানিমাল এর equalsএকটি instanceofচেক করে । কুকুর কুকুর equalsএকটি instanceofচেক আছে। প্রাণী দাও একটি এবং কুকুর (অন্যান্য ক্ষেত্র একই সহ):

a.equals(d) --> true
d.equals(a) --> false

এটি প্রতিসম সম্পত্তি লঙ্ঘন করে।

সমানভাবে চুক্তিটি কঠোরভাবে অনুসরণ করার জন্য, প্রতিসাম্যতা নিশ্চিত করতে হবে, এবং এভাবে শ্রেণিটি একই হওয়া দরকার।


8
এটি এই প্রশ্নের প্রথম পরিষ্কার এবং সংক্ষিপ্ত উত্তর একটি কোড নমুনা এক হাজার শব্দের মূল্যবান।
জনরেড

আপনি দিনটি বাঁচিয়ে ব্যবহার করে অন্য সমস্ত ভার্বোজের উত্তর দিয়ে যাচ্ছিলাম Sএই প্রশ্নের উত্তম, সংক্ষিপ্ত, মার্জিত এবং পুরোপুরি সেরা উত্তর।

1
আপনি উল্লিখিত হিসাবে প্রতিসম প্রয়োজন আছে। তবে "ট্রানজিটিভিটি" প্রয়োজনীয়তাও রয়েছে। যদি a.equals(c)এবং b.equals(c)তারপর, a.equals(b)(তৈরীর সাদাসিধা পদ্ধতির Dog.equalsশুধু return super.equals(object)যখন !(object instanceof Dog)কিন্তু অতিরিক্ত ক্ষেত্র পরীক্ষণ যখন এটি একটি কুকুর উদাহরণস্বরূপ প্রতিসাম্য লঙ্ঘন করবে না কিন্তু transitivity লঙ্ঘন করবে হয়)
শ্যাডো ম্যান

নিরাপদে থাকার জন্য, আপনি একটি getClass()সমতা চেক ব্যবহার করতে পারেন , বা instanceofআপনার equalsএবং hashCodeপদ্ধতিগুলি তৈরি করে আপনি চেক ব্যবহার করতে পারেন final
শ্যাডো ম্যান

26

এটি একটি ধর্মীয় বিতর্কের কিছু বিষয়। উভয় পদ্ধতিরই তাদের সমস্যা রয়েছে।

  • উদাহরণস্বরূপ ব্যবহার করুন এবং আপনি কখনও সাবক্লাসে উল্লেখযোগ্য সদস্য যুক্ত করতে পারবেন না।
  • GetClass ব্যবহার করুন এবং আপনি লিসকভ প্রতিস্থাপন নীতি লঙ্ঘন করেন।

কার্যকর জাভা দ্বিতীয় সংস্করণে ব্লচের আরও একটি প্রাসঙ্গিক পরামর্শ রয়েছে :

  • আইটেম 17: উত্তরাধিকারের জন্য নকশা করুন এবং দস্তাবেজ করুন বা এটি নিষিদ্ধ করুন

1
ব্যবহার সম্পর্কে কিছুই getClassএলএসপিকে লঙ্ঘন করবে না, যদি না বেস ক্লাস নির্দিষ্টভাবে কোনও উপায় নথিভুক্ত করে যার দ্বারা সমান তুলনা করা বিভিন্ন সাবক্লাসগুলির উদাহরণ তৈরি করা সম্ভব হয়। আপনি কী এলএসপি লঙ্ঘন দেখতে পাচ্ছেন?
সুপারক্যাট

সম্ভবত এটি হিসাবে পুনরায় করা উচিত ব্যবহার getClass পুনঃব্যবস্থা করা এবং আপনি এলএসপি লঙ্ঘনের বিপদে সাব টাইপগুলি ছেড়ে যান। কার্যকর জাভাতে ব্লচের একটি উদাহরণ রয়েছে - এটিও এখানে আলোচনা করা হয়েছে । তার যুক্তিটি মূলত এটি যে বিকাশকারীদের সাব টাইপগুলি রাষ্ট্র যুক্ত করে না তা বাস্তবায়নকারীদের জন্য অবাক করা আচরণের কারণ হতে পারে। আমি আপনার বক্তব্য গ্রহণ - ডকুমেন্টেশন কী।
ম্যাকডোয়েল 11

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

1
@ আইয়ালজবা যেখানে উদাহরণস্বরূপ_ ব্যবহৃত হয় যদি একটি সাবক্লাস সদস্যদের সমতুল্য চুক্তিতে যোগ করে এটি প্রতিসম সাম্যতার প্রয়োজনীয়তা লঙ্ঘন করে । GetClass ব্যবহার করে করে পিতামাতার ধরণের সমতুল্য হতে পারে না। আপনি যেভাবেই সমান ওভাররাইড করা উচিত তা নয়, তবে আপনি যদি করেন তবে এটি বাণিজ্য the
ম্যাকডোয়েল

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

23

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

class A { }

class B extends A { }

Object oA = new A();
Object oB = new B();

oA instanceof A => true
oA instanceof B => false
oB instanceof A => true // <================ HERE
oB instanceof B => true

oA.getClass().equals(A.class) => true
oA.getClass().equals(B.class) => false
oB.getClass().equals(A.class) => false // <===============HERE
oB.getClass().equals(B.class) => true

আমার জন্য এটি কারণ
করলিহনস

5

আপনি যদি নিশ্চিত করতে চান যে কেবলমাত্র ক্লাসটি মেলে তবে ব্যবহার করুন getClass() ==। আপনি যদি সাবক্লাসটি মেলাতে চান তবেinstanceof প্রয়োজন।

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

if ( ! (obj instanceof MyClass) ) { return false; }

আপনার দ্বিতীয় বিষয়: তিনি ইতিমধ্যে প্রশ্নের মধ্যে উল্লেখ করেছেন। "আমি সাধারণত উদাহরণস্বরূপ বিকল্পটি যাচাই করি এবং তারপরে প্রবেশ করে 'যদি (اعتراض == নাল)' চেকটি সরিয়ে ফেলি" "
মাইকেল ম্যাইইয়ার্স

5

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

class LastName
{
(...)
}


class FamilyName
extends LastName
{
(..)
}

এখানে আমি 'উদাহরণস্বরূপ' ব্যবহার করব, কারণ আমি চাই পারিবারিক নামের সাথে একটি লাস্টনাম তুলনা করা

class Organism
{
}

class Gorilla extends Organism
{
}

এখানে আমি 'getClass' ব্যবহার করব, কারণ ক্লাসটি ইতিমধ্যে বলেছে যে দুটি দৃষ্টান্ত সমান নয়।


3

উদাহরণস্বরূপ একই শ্রেণি বা এর সাবক্লাসগুলির অন্তর্দৃষ্টিগুলির জন্য কাজ করে

আপনি এটি পরীক্ষার জন্য ব্যবহার করতে পারেন যদি কোনও অবজেক্ট কোনও শ্রেণীর উদাহরণ, সাবক্লাসের উদাহরণ, বা কোনও শ্রেণীর উদাহরণ যা কোনও নির্দিষ্ট ইন্টারফেস প্রয়োগ করে।

অ্যারিয়ালিস্ট এবং রোললিস্ট উভয়ই উদাহরণস্বরূপ তালিকা

যদিও

getClass () == o.getClass () দুটি ক্ষেত্রেই (এটি এবং ও) হুবহু একই শ্রেণীর অন্তর্ভুক্ত হলেই সত্য হবে।

সুতরাং আপনার যা তুলনা করতে হবে তার উপর নির্ভর করে আপনি একটি বা অন্যটি ব্যবহার করতে পারেন।

যদি আপনার যুক্তিটি হ'ল: "একটি অবজেক্টগুলি কেবল তখনই সমান হয় যদি তারা উভয়ই একই শ্রেণি হয়" আপনার "সমান" হওয়া উচিত, যা আমি মনে করি বেশিরভাগ ক্ষেত্রে।


3

উভয় পদ্ধতিতে তাদের সমস্যা রয়েছে।

যদি সাবক্লাসটি পরিচয় পরিবর্তন করে, তবে আপনাকে তাদের প্রকৃত ক্লাসগুলির তুলনা করতে হবে। অন্যথায়, আপনি প্রতিসম সম্পত্তি লঙ্ঘন করেন। উদাহরণস্বরূপ, বিভিন্ন ধরণের Personগুলি সমান হিসাবে বিবেচনা করা উচিত নয়, এমনকি যদি তাদের একই নাম থাকে name

তবে কিছু উপশ্রেণীর পরিচয় পরিবর্তন হয় না এবং এগুলি ব্যবহার করা দরকার instanceof। উদাহরণস্বরূপ, যদি আমাদের অপরিবর্তনীয় Shapeবস্তুগুলির একগুচ্ছ থাকে , তবে Rectangleদৈর্ঘ্য এবং প্রস্থের 1 এর ইউনিটের সমান হওয়া উচিত Square

বাস্তবে, আমি মনে করি আগের ঘটনাটি সত্য হওয়ার সম্ভাবনা বেশি। সাধারণত, সাবক্লাসিং হ'ল আপনার পরিচয়ের একটি মৌলিক অংশ এবং আপনি একটি ছোট্ট কাজ বাদ দিয়ে ঠিক আপনার পিতামাতার মতো হওয়া আপনাকে সমান করে না।


-1

প্রকৃতপক্ষে উদাহরণস্বরূপ পরীক্ষা করুন যে কোনও বস্তুটি কিছু শ্রেণিবিন্যাসের অন্তর্গত বা না। উদাহরণস্বরূপ: গাড়ির অবজেক্টটি যানবাহন শ্রেণীর অন্তর্গত। সুতরাং "Vehical এর নতুন গাড়ি () উদাহরণ" সত্য প্রত্যাবর্তন করে। এবং "নতুন গাড়ি ()। GetClass ()। সমান (Vehical.class)" মিথ্যা প্রত্যাবর্তন, যদিও গাড়ী অবজেক্ট Vehical শ্রেণীর অন্তর্গত তবে এটি পৃথক প্রকার হিসাবে শ্রেণীবদ্ধ করা হয়েছে।

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