简体   繁体   English

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

[英]Hide Public Properties of Base Class in Derived Class

I was wondering if we could hide public properties of Base Class in Derived Class . 我想知道我们是否可以在Derived Class隐藏Base Class public属性。

I have following sample problem statement for calculating Area of different shapes - 我有以下样本问题陈述用于计算不同形状的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;
    }
}

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. 现在有趣的部分是,在Square类中, HeightWidth属性不再需要(因为它被Side属性替换)以暴露给外部wold所以我使用new关键字来隐藏它们。 But it is not working and user now can set Height and Width - 但它不起作用,用户现在可以设置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());
    }
}

Does anyone know in C# is it possible to hide properties of derived class which are not required? 有没有人知道在C#中是否可以隐藏不需要的派生类的属性?

Important Note: One might point out that Shape -> Rectangle -> Square is not a suitable design of inheritance. 重要说明:有人可能会指出Shape -> Rectangle -> Square不是一种合适的继承设计。 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) 但是我想保持这种方式,因为我不想在Square类中再次编写“不完全”但类似的代码(注意: Square类使用其基类RectangleArea方法。在现实世界中,如果是这种类型的继承,方法逻辑可能更复杂)

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. 您也可以使用override执行类似的操作,如果访问器(特别是set )使用不当,甚至可能throw

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. 我仍然认为Shape -> Rectangle -> Square是所有问题的根源。 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. 如果你有相似的代码来计算区域,你可以组成逻辑:即将区域计算的逻辑外部化为一个单独的类,并在Square和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 ) (您可能还想了解Liskov替代原则

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 : 首先想到的是,我认为我会将RectangleHeightWidth声明为virtual并在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;
    }
}

What is an advantage of Square inheritance from Rectangle ? RectangleSquare继承有什么优势? 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 如果您仍然需要SquareShape的公共对象,那么您可以定义

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. 我回应@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. 组合是一种更好的解决方案,必要时委托给另一个(基类)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM