I am writing a program that calculates the distance between 2 points in 2 dimensional space and 3 dimensional space.
I have created two classes "2DPoint" and "3DPoint". 3DPoint inherits from 2DPoint.
I have a "calculateDistance" method in 2DPoint which i want to override in 3DPoint.
Here is the code in 2DPoint:
public virtual double calcDistan开发者_如何转开发ce(int xco1, int xco2, int yco1, int yco2)
{
.....(some maths)
return distance;
}
Now the problem im having is in 3DPoint i have to feed in X, Y and then a Z co-ordinate for 2 points and so by stating "override" in the 3DPoint class it wont let me override the method in 2D Point.
e.g.
public override double calcDistance(int xco1, int xco2, int yco1, int yco2, int zco1, int zco2)
{
.....(some maths)
return distance;
}
So I have 3 questions:
- Is it at all possible to override the 2DPoint calcDistance using the override command how i have written the code?
- If not is there a way around my problem using the override command?
- Is overloading the same as overriding, because that is the only way around it i can see.
This is a relatively simple misunderstanding.
- Overriding is a means to change behaviour of a routine in a subclass. An overridden method has the same parameters as the original.
- Overloading is when you have methods with the same name but different parameters. The compiler works out which one you mean by matching the parameters.
I can't see enough of your code to know if your basic design is sound, but on the face of it it would seem that you need to use overloading.
You shouldn't have to override a 2-parameter function, just create a new function with the 3 parameters. When an instance of the 3d is created, it will be visible to the calling source. By having a different "Signature" of 3 parameters (or even same # of parameters, but different types), the compiler will know which function it should be calling. Ex:
public class Calc2d
{
public virtual CalcDistance( int Parm1, int parm2 )
{ ... }
}
public class Calc3d : Calc2d
{
public virtual CalcDistance( int Parm1, int parm2, int Parm3 )
{ ... }
}
In the 3d class, BOTH instance of the CalcDistance will be visible, but depending on how many parameters are passed will dictate which instance is invoked.
First off, you cannot possibly creaate 2DPoint
and 3DPoint
classes. Next, I really doubt that a 3D point should inherit from 2D point.
As for your questions,
- Overriding requires parameters to be identical (to put simply)
- No, there's nothing to override here
- Yes, overloading is different from overriding
You should not let 3DPoint be a subclass of 2DPoint as this is not a is-a relation. A 2D point is not a generalization of a 3D point, there are just different and should not inherit one from the other.
Btw, I don't understand your method signature public virtual double calcDistance(int xco1, int xco2, int yco1, int yco2)
. It takes coordinates of the points even though its an instance method and therefore is always performed on a specific point. Something like public virtual double calcDistance(2DPoint other)
would make more sense to me.
A better design to your problem and appropriately use polymorphism will be to create 2D point class that takes in the 4 parameter (Xs and Ys) in the constructor. Then a 3D point class that takes in 6 parameters (Xs, Ys and Zs).
You will then write in 2DPoint
public virtual double calcDistance()
and 3DPoint
public override double calcDistance()
1) You can't change the parameters that are taken when overriding methods. If you try to do this you'll end up with two methods available on your sub-class.
3) Overloading is where you have a method that takes different sets of parameters e.g. Calc(int x)
and Calc(int x, int y)
. This is different to overriding as overriding changes the behaviour in one class compared to that of it's base class.
You could do one of a number of things:
i) Make your method operate on an interface. IPoint. Check the type of the IPoint, if it's a 2DPoint and you expected a 3dPoint then throw an exception. You can add generics to make it strongly typed. This is probably the approach I would take. It ensures that you call the correct method, and will complain at compile time rather than runtime.
interface IPoint<TPoint> where TPoint : IPoint
{
Double CalcuateDistance(TPoint point);
}
public class 2DPoint : IPoint<2DPoint>
{
public Double X { get; set; }
public Double Y { get; set; }
public Double CalculateDistance(2DPoint point)
{
// some maths using this.X/this.Y and point.X/point.Y
}
}
public class 3DPoint : IPoint<3DPoint>
{
public Double X { get; set; }
public Double Y { get; set; }
public Double Z { get; set; }
public Double CalculateDistance(3DPoint point)
{
// some maths using this.X/this.Y/this.Z and point.X/point.Y/point.Z
}
}
Using this approach, if you had common functionality to both types of point you could place that in a base abstract class instead AbstractPoint<TPoint> : IPoint<TPoint>
. If you did it this way you would define:
abstract class AbstractPoint<TPoint> : IPoint<TPoint>
{
public virtual double CalculateDistance(TPoint point);
}
When you override this in 2DPoint and 3DPoint then you will automatically have the correct type of TPoint being passed in :)
ii) Make your base class method take a z, which has a default value of 0. Just pass in 0 for all 2D points. This is the same as having 2 methods on your base (one that takes a z, ones that doesn't and calling the right one at the right time)
Calc(int x, int y, int z = 0);
iii) Remove the inheritance and have 2 separate concerete classes.
精彩评论