কিলিয়ান ফথের উত্তরটি দুর্দান্ত। এই সমস্যাটি কেন, এর ক্যানোনিকাল উদাহরণ * আমি যুক্ত করতে চাই। একটি পূর্ণসংখ্যা পয়েন্ট শ্রেণীর কল্পনা করুন:
class Point2D {
public int x;
public int y;
// constructor
public Point2D(int theX, int theY) { x = theX; y = theY; }
public int hashCode() { return x + y; }
public boolean equals(Object o) {
if (this == o) { return true; }
if ( !(o instanceof Point2D) ) { return false; }
Point2D that = (Point2D) o;
return (x == that.x) &&
(y == that.y);
}
}
এখন এটি একটি 3 ডি পয়েন্ট হতে সাব-শ্রেণীর করা যাক।
class Point3D extends Point2D {
public int z;
// constructor
public Point3D(int theX, int theY, int theZ) {
super(x, y); z = theZ;
}
public int hashCode() { return super.hashCode() + z; }
public boolean equals(Object o) {
if (this == o) { return true; }
if ( !(o instanceof Point3D) ) { return false; }
Point3D that = (Point3D) o;
return super.equals(that) &&
(z == that.z);
}
}
সুপার সরল! আসুন আমাদের পয়েন্টগুলি ব্যবহার করুন:
Point2D p2a = new Point2D(3, 5);
Point2D p2b = new Point2D(3, 5);
Point2D p2c = new Point2D(3, 7);
p2a.equals(p2b); // true
p2b.equals(p2a); // true
p2a.equals(p2c); // false
Point3D p3a = new Point3D(3, 5, 7);
Point3D p3b = new Point3D(3, 5, 7);
Point3D p3c = new Point3D(3, 7, 11);
p3a.equals(p3b); // true
p3b.equals(p3a); // true
p3a.equals(p3c); // false
আপনি সম্ভবত ভাবছেন যে কেন আমি এত সহজ উদাহরণ পোস্ট করছি। এখানে ধরা আছে:
p2a.equals(p3a); // true
p3a.equals(p2a); // FALSE!
আমরা যখন 2 ডি পয়েন্টটির সমতুল্য 3 ডি পয়েন্টের সাথে তুলনা করি তখন আমরা সত্য হয়ে উঠি, কিন্তু আমরা যখন তুলনাটি উল্টো করি তখন আমরা মিথ্যা হয়ে যাই (কারণ পি 2 এ ব্যর্থ হয় instanceof Point3D
)।
উপসংহার
একটি সাবক্লাসে কোনও পদ্ধতি এমনভাবে প্রয়োগ করা সাধারণত সম্ভব যে এটি সুপার-ক্লাসটি কীভাবে কাজ করবে আশা করে তার সাথে আর সুসংগত নয়।
সাধারণত পিতা-মাতার শ্রেণীর সাথে সামঞ্জস্যপূর্ণ এমন উপাখণ্ডে সমান () সমান প্রয়োগ করা অসম্ভব।
যখন আপনি এমন একটি ক্লাস লেখেন যা আপনি লোককে সাবক্লাসে যাওয়ার অনুমতি দেওয়ার ইচ্ছা করেন তখন প্রতিটি পদ্ধতির কীভাবে আচরণ করা উচিত সে সম্পর্কে একটি চুক্তি লিখে রাখা সত্যিই ভাল ধারণা । আরও ভাল হবে ইউনিট পরীক্ষাগুলির একটি সেট যা তারা চুক্তি লঙ্ঘন করে না তা প্রমাণ করার জন্য ওভাররাইড পদ্ধতিগুলি তাদের প্রয়োগের বিরুদ্ধে চালাতে পারে। প্রায় কেউই তা করে না কারণ এটি খুব বেশি কাজ। তবে আপনি যদি যত্নশীল হন, তবে এটি করার জিনিস।
একটি ভাল বানানযুক্ত চুক্তির একটি দুর্দান্ত উদাহরণ হল তুলনামূলক । .equals()
উপরে বর্ণিত কারণে এটি কী বলে তা কেবল উপেক্ষা করুন । তুলনামূলক কীভাবে জিনিসগুলি .equals()
করতে পারে না তার একটি উদাহরণ এখানে ।
নোট
জোশ ব্লচের "কার্যকর জাভা" আইটেম 8 এই উদাহরণটির উত্স ছিল তবে ব্লচ একটি রঙিন পয়েন্ট ব্যবহার করেছে যা তৃতীয় অক্ষের পরিবর্তে একটি রঙ যুক্ত করে এবং ইনটগুলির পরিবর্তে ডাবল ব্যবহার করে। ব্লচের জাভা উদাহরণটি মূলত ওডারস্কি / চামচ / ভেনার্স দ্বারা নকল করা হয়েছে যারা তাদের উদাহরণ অনলাইনে উপলব্ধ করেছেন।
বেশিরভাগ লোক এই উদাহরণটিতে আপত্তি করেছে কারণ আপনি যদি পিতামাত্ত শ্রেণিকে উপ-শ্রেণীর সম্পর্কে জানাতে থাকেন তবে আপনি এই সমস্যাটি সমাধান করতে পারেন। এটি সত্য যদি খুব কম সংখ্যক সাব-ক্লাস থাকে এবং পিতা-মাতার যদি সেগুলি সম্পর্কে সমস্ত জানা থাকে। তবে মূল প্রশ্নটি এমন একটি এপিআই তৈরির বিষয়ে ছিল যা অন্য কেউ সাব-ক্লাস লিখবে। সেক্ষেত্রে আপনি সাধারণত সাব-ক্লাসগুলির সাথে সামঞ্জস্যপূর্ণ হওয়ার জন্য প্যারেন্ট প্রয়োগটি আপডেট করতে পারবেন না।
বোনাস
তুলনাকারীটিও আকর্ষণীয় কারণ এটি সমান () সঠিকভাবে প্রয়োগের বিষয়টি নিয়ে কাজ করে। আরও ভাল, এটি উত্তরাধিকার ইস্যু এই ধরণের ঠিক করার জন্য একটি প্যাটার্ন অনুসরণ: কৌশল নকশা প্যাটার্ন। হাস্কেল এবং স্কালার যে প্রকারভেদগুলি সম্পর্কে উত্সাহিত হয় সেগুলি কৌশল কৌশলও। উত্তরাধিকার খারাপ বা ভুল নয়, এটি কেবল কৌশল। আরও পড়ার জন্য, ফিলিপ ওয়েডলারের কাগজটি দেখুন কীভাবে অ্যাড-হক পলিমারফিজমকে কম অ্যাড-হক তৈরি করবেন