OOP in Math

   My coworker Lyubo came up with the following OOP problem while we were having lunch the other day. He says it is a well known problem that you can see on numerous places but it is new to me.

   We know from mathematics that the square is a special case of rectangle. In OOP terms "special case" means inheritance. Obviously the mathematical square inherits from mathematical rectangle. Your task is to create OOP model for that relationship. Lets say that we want the rectangle to expose get property (getter for you Java readers) – the area of the rectangle. This is not as simple as it sounds. Here is one of the simplest (and very wrong) solutions:

   class Rectangle
   {
       /// <summary>
       /// A side of the rectangle
       /// </summary>
       public uint A { get; set; }

       /// <summary>
       /// B side of the rectangle
       /// </summary>
       public uint B { get; set; }

       virtual public uint Area
       {
           get { return A * B; }
       }
   }

   class Square : Rectangle
   {
       public override uint Area
       {
           get
           {
               return A * A;
           }
       }
   }

However this means that the B property is not actually used. This can lead to unexpected results in polymorphic client code. We expect a rectangle to have a area of A*B and somehow it will not if it is an instance of Square. We can override the property setters, add some exceptions but what inheritance means is that the child class can do ANYTHING that the base class can. If you need to add special case behavior for any of the child classes then the inheritance hierarchy you have created is simply wrong. So go ahead make it right... (or read ahead for explanation)

I am proud to say that after giving several wrong answers I found the correct one on my own. Here is the right implementation:

   class Rectangle
   {
       private Rectangle()
       {
       }

       public Rectangle(uint a, uint b)
       {
           this.a = a;
           this.b = b;
       }

       private uint a;

       /// <summary>
       /// Gets A side of the rectangle
       /// </summary>
       public uint A
       {
           get { return a; }
       }

       private uint b;
       /// <summary>
       /// Gets B side of the rectangle
       /// </summary>
       public uint B
       {
           get { return b; }
       }

       public uint Area
       {
           get { return A * B; }
       }
   }

   class Square : Rectangle
   {
       public Square(uint a)
           : base(a, a)
       {
       }
   }

   That is right the classes should be immutable. Why? Because the mathematical objects that they represent are in fact immutable. If we want to use the relationship that mathematics teaches us we must conform to its rules. As most objects in mathematics geometric figures are immutable. There is no assignment operator nor setters in mathematics.

   On a side note functional programing that is supposed to be more mathematical makes heavy use of immutability. Now I see why.
Tags:   english programming 
Posted by:   Stilgar
00:20 25.10.2008

Comments:

First Previous 1 Next Last 

Posted by   ___XXX_X_XXX___ (Unregistered)   on   02:56 25.10.2008

Моля моля :) Искам и аз да се изсера на метеното !
Тея глупости в отделно асембли:
public class Tetragon
{
   public double A { get; internal set; }
   public double B { get; internal set; }
   public double C { get; internal set; }
   public double D { get; internal set; }
   internal Tetragon() { }
   // Както се сещате - става само за квадрат и правоъгълник. Добре че има "virtual" :)
   public virtual double Surface { get { return A * B; } }
}

public class Rectangle : Tetragon { internal Rectangle() { } }

public class Square : Tetragon { internal Square() { } }

public class Trapez : Tetragon { internal Trapez() { } public override double Surface { get { return (this.A + this.B) * this.C / 2; } } }

public static class TetragonFactory
{
   public static Trapez CreateTrapez(double a, double b, double h) { return new Trapez { A = a, B = b, C = h }; }
   public static Rectangle CreateRectangle(double a, double b) { return new Rectangle { A = a, B = b }; }
   public static Square CreateSquare(double a) { return new Square { A = a, B = a }; }
}


Ето го и клиента. Да си направи и референция към горните :)
class Program
{
   static void Main(string[] args)
   {
       Trapez t = TetragonFactory.CreateTrapez(7, 12, 9);
       Rectangle r = TetragonFactory.CreateRectangle(2, 3);
       Square s = TetragonFactory.CreateSquare(5);
       Console.WriteLine(t.Surface);
       Console.WriteLine(r.Surface);
       Console.WriteLine(s.Surface);
       Console.ReadLine();
   }
}

И ся... Няма проверки за отрицателни (ИЛИ НУЛЕВИ Stilgar-е !!! :) ) стойности, ама ако клиента не знае че квадрат със страна 0 не е квадрат, да ходи да става докер.

Posted by   Guest (Unregistered)   on   03:07 25.10.2008

Забравих да кажа, че Square е частен случай на четириъгълник, Rectangle също, Trapez също, ама щеше да изглежда и да се maintain-ва кофти, ако ги навържа Square : Rectangle : Trapez : Tetragon (или подобен ред) :)

Posted by   Stilgar   on   15:04 25.10.2008

Bah tva kolko e enterprise!

Posted by   FidelDahan (Unregistered)   on   04:59 30.10.2008

He-he, this is a famous fundamental problem with inheritance. I don't know if making the classes immutable, just for the sake of applying inheritance is good. But that way it doesn't break the principle of substitution. Anyway, it may not be sane to follow the mathematic relationship, because mathematic objects have no behaviour. And behaviour matters in OOP.

http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.6

Posted by   Stilgar   on   12:32 30.10.2008

Unless it is in the definition of the problem that you need to model mathematical rectangle/square :)

if it is not then you need more information on what exactly you are modeling and probably you'll find out that the things you are modeling do not inherit from each other and they probably shouldn't be called square and rectangle

First Previous 1 Next Last 


Post as:



Post a comment: