You almost had this (theoretically):
public class Point { public virtual double sideA, sideB, radius, height; } public class RightTriangle:Point { public override double sideA, sideB; }
For properties and methods to be overridden in derived classes, they must be declared virtual in the base class. The override class must declare the override property / method as an override .
In practice, you cannot create virtual fields; there can only be properties and methods. Therefore, you need to change your code as follows:
public class Point { public virtual double sideA { get; set; } public virtual double sideB { get; set; } public virtual double radius { get; set; } public virtual double height { get; set; } } public class RightTriangle:Point { public override double sideA { get; set; } public override double sideB { get; set; } }
However, you should not do this, as this is a very poor design. Lower.
So what's the difference in new ?
When a method is overridden, it will be determined at run time whether the overridden or original implementation will be called.
So, when a method receives a Point argument as an argument, the Point instance can actually be a RightTriangle or Circle .
Point p1 = new RightTriangle(); Point p2 = new Circle();
In the above example, both p1 and p2 are Point in terms of the code that uses p1 and p2 . However, "below them" they are in fact instances of derived classes.
So, with my solution, for example, when you use p1.sideA , the runtime will look βbelowβ and check that there really is a Point : is it a RightTriangle ? Then check if there is an overridden implication of sideA and call it. Is it really Circle ? Then perform the same test (which will not be performed) and call the original sideA implantation.
Qualifying new , however, is doing something else. It will not override the method, but will create a completely new one (with the same name), which is processed differently at compile time.
So, with your solution, the compiler sees that you created a RightTriangle and saved it in a variable of type Point . When you now access p1.sideA , for example, the compiler will compile this access so that it sideA from the base class, since the instance variable you are dealing with is of the base type.
If you still want to access the new implementation, then your code using p1 must pass it into the correct derived RightTriangle type:
var w = ((RightTriangle)p1).sideA;
So what's the problem?
As you already noticed, using new not a good solution. Code that uses all types of Point needs to know whether a particular derived value of Point implements a field with new or not. In addition, he should know when he receives an instance of Point , which instance is under it. This will lead to many very complex if - else that check which p1 points are processed and the corresponding actions are performed.
Using virtual and override eliminates the last problem, but only if the base class implements all the methods and properties that any derived class implements. Which in essence is crazy. You tried this, and I'm sure you noticed that it makes no sense to give Point a sideA and sideB and radius . How does Point ever implement these properties meaningfully? And you cannot make them abstract , because then Circle also had to implement sideA , etc.
So how to solve the problem better?
Think about what you want to do with these instances of differnet points. You put them together on a list for some reason: they have something in common. You also iterate over this list and do something with each of them for a specific reason. But what are you trying to do for sure? Can you describe this in an abstract way?
Maybe you get lateral lengths and radii to calculate the area? Then give Point a virtual the GetArea() method and override it in each derived class. The GetArea() method makes sense for all derived types, although it is implemented differently in each of them.
You can also make GetArea() a abstract instead of virtual . This means that it is not implemented at all in the base class, and all derived types enforce it independently.
Maybe you do not want to process all Point in the list, but only RightTriangle ? Then the code executing this should receive only RightTriangle s:
public void HandleRightTriangles(IEnumerable<RightTriangle> rts) {
Call the following address: