I was wondering if we could hide public
properties of Base Class
in Derived Class
.
I have following sample problem statement for calculating Area
of different shapes -
abstract class Shape
{
public abstract float Area();
}
class Circle : Shape
{
private const float PI = 3.14f;
public float Radius { get; set; }
public float Diameter { get { return this.Radius * 2; } }
public Circle() { }
public Circle(float radius)
{
this.Radius = radius;
}
public override float Area()
{
return PI * this.Radius * this.Radius;
}
}
class Triangle : Shape
{
public float Base { get; set; }
public float Height { get; set; }
public Triangle() { }
public Triangle(float @base, float height)
{
this.Base = @base;
this.Height = height;
}
public override float Area()
{
return 0.5f * this.Base * this.Height;
}
}
class Rectangle : Shape
{
public float Height { get; set; }
public float Width { get; set; }
public Rectangle() { }
public Rectangle(float height, float width)
{
this.Height = height;
this.Width = width;
}
public override float Area()
{
return Height * Width;
}
}
class Square : Rectangle
{
public float _side;
public float Side
{
get { return _side; }
private set
{
_side = value;
this.Height = value;
this.Width = value;
}
}
// These properties are no more required
// so, trying to hide them using new keyword
private new float Height { get; set; }
private new float Width { get; set; }
public Square() : base() { }
public Square(float side)
: base(side, side)
{
this.Side = side;
}
}
Now interesting part is here that in Square
class Height
& Width
properties are no more required (as it is replaced by Side
property) to expose to outer wold so I am using new
keyword to hide them. But it is not working and user now can set Height
and Width
-
class Program
{
static void Main(string[] args)
{
Shape s = null;
// Height & Width properties are still accessible :(
s = new Square() { Width = 1.5f, Height = 2.5f };
Console.WriteLine("Area of shape {0}", s.Area());
}
}
Does anyone know in C# is it possible to hide properties of derived class which are not required?
Important Note: One might point out that Shape -> Rectangle -> Square
is not a suitable design of inheritance. But I would like to keep it that way because I do not want to write "not exact" but similar code again in Square
class (note: Square
class makes use of Area
method of its base class Rectangle
. In real world, in case of such type of inheritance that method logic may be more complicated)
Any sub-type is still fundamentally capable of being treated an instances of the base-type. You certainly can't hide the members if someone has a variable typed as the base-type . The most you can do would be to make them really annoying to use when using the derived type , for example:
[Obsolete, Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new float Width { get { return base.Width;} }
You could also do something similar with override
, and possibly even throw
if the accessors (the set
in particular) are used inappropriately.
However, it sounds more like you should be changing the inheritance model such that you never want to try to remove members.
I still think that Shape -> Rectangle -> Square
is the source of all problems. Inheritance is not just about code reuse. If you have similar code to compute area, you can compose the logic: ie externalize the logic of area computation to a separate class, and reuse that in Square and Rectangle.
Coming back to your original question, the fact that you need to hide properties in the base class from the child classes is a big design smell - and the language designers would most definitely not have wanted such a feature.
(You may also want to read about Liskov Substitution Principle )
At first thought, I think I would declare Rectangle
's Height
and Width
as virtual and override it in the Square
class, instead of trying to hide them :
class Square : Rectangle
{
public float Side{get;set;}
public override float Height { get{return Side;}; set{Side =value;} }
public override float Width {get{return Side;}; set{Side =value;} }
public Square() : base() { }
public Square(float side)
{
this.Side = side;
}
}
What is an advantage of Square inheritance from Rectangle ? Maybe you need a new class like:
abstract class Square<TFigure> where TFigure : Shape
{
public float Side {set; get;}
protected Square(TFigure stereotype)
{
Side = GetStereotypeSide(stereotype)
}
public abstract float GetStereotypeSide(TFigure stereotype);
}
then your square can look like following
class RectangleSquare: Square<Rectangle>
{
public RectangleSquare() : base (new Rectangle(){Height = 1, Width = 2})
{
}
public override float GetStereotypeSide(Rectangle stereotype)
{
return stereotype.Height*stereotype.Width;
}
}
in case you still need a common object for Square and Shape than you can define
interface IGeometry{
}
and then add the interface inheritance to both classes
class Shape : IGeometry
....
and
abstract class Square<TFigure> : IGeometry where TFigure : Shape
I echo @aquaraga. If you desire to hide what's public in a base class then derivation is not right. Composition is a better solution, delegating to the the other (base) class when necessary.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.