ডেরাইভড টাইপগুলো তাদের বেস টাইপের জন্য সম্পূর্ণরূপে সাবস্টিটিউটেবল হতে হবে।
সংজ্ঞা:
আমাদের একটি চাইল্ড ক্লাসকে প্যারেন্ট ক্লাস হিসেবে বরততে পারা উচিত। এসেনশিয়ালি এর মানে হলো সকল ডেরাইভড ক্লাস তাদের প্যারেন্ট ক্লাসের ফাংশন্যালিটি রিটেইন করবে এবং প্যারেন্ট যা প্রদান করে তা রিপ্লেস করবে না।
লিস্কভ সাবস্টিটিউশন প্রিন্সিপল লঙ্ঘন (Before)
public class Ellipse
{
public double MajorAxis { get; set; }
public double MinorAxis { get; set; }
public virtual void SetMajorAxis(double majorAxis) { this.MajorAxis = majorAxis; }
public virtual void SetMinorAxis(double minorAxis) { this.MajorAxis = minorAxis; } // বাগ: MinorAxis সেট করা হয়নি
public virtual double Area() { return MajorAxis * MinorAxis * Math.PI; }
}
public class Circle : Ellipse
{
public override void SetMajorAxis(double majorAxis)
{
base.SetMajorAxis(majorAxis);
this.MinorAxis = majorAxis; // সার্কেলে দুটি অক্ষ সমান
}
}
public class Result
{
public void Method1()
{
Circle circle = new Circle();
circle.SetMajorAxis(5);
circle.SetMinorAxis(4);
var area = circle.Area(); // 5*4 = 20, কিন্তু আশা 5*5 = 25
}
}
সমস্যা: Circle হলো Ellipse কিন্তু এর বিহেভিয়ার ভিন্ন। SetMinorAxis কল করলে সার্কেলের রেডিয়াস পরিবর্তন হয়, যা এলিপসের নিয়ম লঙ্ঘন করে।
লিস্কভ সাবস্টিটিউশন প্রিন্সিপল অনুপালন (After)
internal class Program
{
private static void Main() { }
}
public class Ellipse
{
public double MajorAxis { get; set; }
public double MinorAxis { get; set; }
public virtual void SetMajorAxis(double majorAxis) { MajorAxis = majorAxis; }
public virtual void SetMinorAxis(double minorAxis) { MajorAxis = minorAxis; } // এখানও বাগ আছে, কিন্তু উদাহরণের জন্য
public virtual double Area() { return MajorAxis * MinorAxis * Math.PI; }
}
public class Circle : Ellipse
{
public override void SetMajorAxis(double majorAxis)
{
base.SetMajorAxis(majorAxis);
this.MinorAxis = majorAxis;
}
public override void SetMinorAxis(double minorAxis)
{
base.SetMinorAxis(minorAxis);
this.MajorAxis = minorAxis;
}
public override double Area() { return base.Area(); }
}
public class Circle1 // ভালো ডিজাইন: সার্কেল আলাদা ক্লাস, Ellipse থেকে ইনহেরিট না করে
{
public double Radius { get; set; }
public void SetRadius(double radius) { this.Radius = radius; }
public double Area() { return this.Radius * this.Radius * Math.PI; }
}
ব্যাখ্যা: সঠিক LSP অনুপালনের জন্য Circle1-এর মতো আলাদা ক্লাস তৈরি করা ভালো, যা Ellipse থেকে ইনহেরিট করে না। ইনহেরিটেন্স "ইজ-এ" (is-a) রিলেশনশিপ মেনে চলতে হয়, শুধু কোড রিয়ুজের জন্য নয়।