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