隐藏派生类中基类的公共属性

时间:2013-06-07 12:47:30

标签: c# oop design-patterns inheritance

我想知道我们是否可以在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关键字来隐藏它们。但它不起作用,用户现在可以设置newHeight -

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。在现实世界中,在这种类型的继承的情况下,方法逻辑可能更复杂)

5 个答案:

答案 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。如果你想隐藏基类中的公共内容,那么推导是不对的。组合是一种更好的解决方案,在必要时委托给另一个(基础)类。