Scott Mason wrote:
> I've been futzing around with a piece of code that works, but I'm hoping 
> there 
> is a more elegant way to do they following.
> 
> I've got a graphical application with four basic items.
> - a single point object
> - a two point object (line segment)
> - a three point object (arc)
> - a multi point object (polygon)
> 
> The user can select any two items and have the system calculate the distance 
> between them.  Each type of comparison has its own function so the code looks 
> something like this (all of the type casting has been removed to make the 
> code a 
> little cleaner)
> 
> A = object 1
> B = object 2
> 
> lfDistance := SOME_WEIRD_CONSTANT;
> 
> if ((A.Points = 1) and (B.Points = 1)) then
>    lfDistance := geo.Distance(A.P1, B.P1);
> 
> if ((A.Points = 1) and (B.Points = 2)) then
>    lfDistance := geo.Distance(A.P1, B.P1, B.P2);
> 
> if ((A.Points = 1) and (B.Points = 3)) then
>    lfDistance := geo.Distance(A.P1, B.PC, B.P1, B.P2);
> 
> if ((A.Points = 1) and (B.Points > 3)) then
>    lfDistance := geo.Distance(A.P1, B);
> 
> if ((A.Points = 2) and (B.Points = 1)) then
>    lfDistance := geo.Distance(B.P1, A.P1, A.P2);
> 
> if ((A.Points = 2) and (B.Points = 2)) then
>    lfDistance := geo.Distance(A.P1, A.P2,  B.P1, B.P2);
> 
> ... and so one for every permutation
> 
> if (lfDistance <> SOME_WEIRD_CONSTANT) then
>    // Display the distance
> 
> 
> If there a better way to do this kind of comparison?

Each of the four classes descends from a common base class that has 
these five virtual methods:

type
   TGeoObject = class
   protected
     function DistanceFrom(const Other: TGeoPoint): Double; overload; 
virtual; abstract;
     function DistanceFrom(const Other: TGeoLine): Double; overload; 
virtual; abstract;
     function DistanceFrom(const Other: TGeoArc): Double; overload; 
virtual; abstract;
     function DistanceFrom(const Other: TGeoPolygon): Double; overload; 
virtual; abstract;
   public
     function DistanceTo(const Other: TGeoObject): Double; virtual; 
abstract;
   end;

Each class overrides the DistanceFrom methods in its own way to 
determine the distance between itself and the given other classes of 
object. Each class also overrides DistanceTo like this:

function TGeoPoint.DistanceTo(const Other: TGeoObject): Double;
begin
   Result := Other.DistanceFrom(Self);
end;

function TGeoLine.DistanceTo(const Other: TGeoObject): Double;
begin
   Result := Other.DistanceFrom(Self);
end;

The protected DistanceFrom methods do the real work, but polymorphism 
figures out which work to do based on the types of the objects being 
compared. The code works without any "if" statements -- some of the 
checking happens at compile time by figuring out which overloaded method 
to call, and the rest of the checking happens at run time by calling 
DistanceTo virtually.

There's a special name for this technique. I wish I could remember it. 
Some kind of polymorphism.

-- 
Rob
__________________________________________________
Delphi-Talk mailing list -> [email protected]
http://www.elists.org/mailman/listinfo/delphi-talk

Reply via email to