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

本文关键字:属性 基类 隐藏 派生 | 更新日期: 2023-09-27 18:17:19

我想知道我们是否可以在Derived Class中隐藏Base Classpublic属性。

我有以下示例问题语句用于计算不同形状的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属性不再需要(因为它被Side属性所取代)暴露给外部世界,所以我使用new关键字来隐藏它们。但是它不工作,用户现在可以设置HeightWidth -

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());
    }
}

有谁知道在c#中隐藏派生类的属性是不需要的吗?

重要提示:有人可能会指出Shape -> Rectangle -> Square不是一个合适的继承设计。但我想保持这种方式,因为我不想在Square类中再次编写"不精确"但类似的代码(注意:Square类使用其基类RectangleArea方法。在现实世界中,对于这种类型的继承,方法逻辑可能会更复杂)

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

任何子类型基本上仍然能够被视为基类型的实例。如果有人将变量作为基类型,则当然不能隐藏成员。你最多能做的就是在使用派生类型时让他们非常讨厌使用,例如:

[Obsolete, Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new float Width { get { return base.Width;} }

您也可以对override做类似的事情,如果访问器(特别是set)使用不当,甚至可能是throw

然而,听起来更像是您应该更改继承模型,使永远不希望尝试删除成员。

我仍然认为Shape -> Rectangle -> Square是所有问题的根源。继承不仅仅是关于代码重用。如果你有类似的代码来计算面积,你可以组成逻辑:也就是说,将面积计算的逻辑外部化到一个单独的类中,并在Square和Rectangle中重用。

回到你最初的问题,你需要在子类中隐藏基类中的属性,这是一个很大的设计气味——语言设计者绝对不希望有这样的特性。

(您可能还想阅读有关Liskov替代原理)

一想到,我想我会声明RectangleHeightWidth为虚拟的,并在Square类中覆盖它,而不是试图隐藏它们:

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;
    }
}

矩形继承正方形的优点是什么?也许你需要一个新的类,比如:

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;
  }
}
如果您仍然需要SquareShape的公共对象,则可以定义
interface IGeometry{
}

,然后将接口继承添加到两个类

    class Shape : IGeometry
  ....

abstract class Square<TFigure> : IGeometry where TFigure : Shape

我返回@aquaraga。如果您希望隐藏基类中的公共内容,则派生是不正确的。组合是一个更好的解决方案,在必要时委托给另一个(基)类。