我想知道我们是否可以在public
中隐藏Base Class
的{{1}}属性。
我有以下样本问题陈述用于计算不同形状的Derived Class
-
Area
现在有趣的部分在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;
}
}
班Square
&不再需要Height
属性(因为它被Width
属性替换)以暴露给外部wold,因此我使用Side
关键字来隐藏它们。但它不起作用,用户现在可以设置new
和Height
-
Width
有没有人知道在C#中是否可以隐藏不需要的派生类的属性?
重要提示:
有人可能会指出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());
}
}
不是一种合适的继承设计。但我希望保持这种方式,因为我不想在Shape -> Rectangle -> Square
类中再次编写“不完全”但类似的代码(注意:Square
类使用Square
方法它的基类Area
。在现实世界中,在这种类型的继承的情况下,方法逻辑可能更复杂)
答案 0 :(得分:5)
任何子类型基本上都能够被视为基类型的实例。如果有人将变量键入为基本类型,您肯定无法隐藏成员。你能做的最多就是在使用派生类型时使用会让他们感到烦恼,例如:
[Obsolete, Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new float Width { get { return base.Width;} }
如果访问者(特别是override
)使用不当,您也可以使用throw
执行类似操作,甚至可能执行set
。
但是,听起来更像是应该更改继承模型,以免您想要尝试删除成员。
答案 1 :(得分:3)
我仍然认为Shape -> Rectangle -> Square
是所有问题的根源。继承不仅仅是代码重用。如果您有相似的计算区域代码,您可以撰写逻辑:即将区域计算逻辑外部化为单独的类,并在Square和Rectangle中重复使用。
回到你原来的问题,你需要从子类隐藏基类中的属性这一事实是一个很大的设计气味 - 而语言设计者绝对不会想要这样的功能。
(您可能还想了解Liskov Substitution Principle)
答案 2 :(得分:1)
首先想一想,我想我会将Rectangle
的{{1}}和Height
声明为虚拟并在Width
类中覆盖它,而不是试图隐藏它们:
Square
答案 3 :(得分:1)
矩形的 Square 继承有什么优势? 也许你需要一个新的类,如:
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);
}
然后您的方块可能如下所示
class RectangleSquare: Square<Rectangle>
{
public RectangleSquare() : base (new Rectangle(){Height = 1, Width = 2})
{
}
public override float GetStereotypeSide(Rectangle stereotype)
{
return stereotype.Height*stereotype.Width;
}
}
如果你仍然需要 Square 和 Shape 的公共对象而不是你可以定义的
interface IGeometry{
}
然后将接口继承添加到两个类
class Shape : IGeometry
....
和
abstract class Square<TFigure> : IGeometry where TFigure : Shape
答案 4 :(得分:0)
我回应@aquaraga。如果你想隐藏基类中的公共内容,那么推导是不对的。组合是一种更好的解决方案,在必要时委托给另一个(基础)类。