How to hide an inherited property in a class without modifying the inherited class (base class)?

前端 未结 10 818
无人共我
无人共我 2020-11-27 20:21

If i have the following code example:

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA :         


        
相关标签:
10条回答
  • 2020-11-27 20:33

    I think it is bad design if you have to do this, especially if you are able to design the code from the ground up.

    Why?

    Good design is to let the base-class share common properties that a certain concept has (virtual or real). Example: System.IO.Stream in C#.

    Further down the lane bad design will increase the cost for maintenance and make implementation harder and harder. Avoid this as much as possible!

    Basic rules which I use:

    • Minimize the number of properties and methods in the base-class. If you do not expect to use some properties or methods in a class that inherits the base class; do not put it in the baseclass then. If you are in the developmentstage of a project; always go back to the drawing-board now an then to check the design because things change! Redesign when needed. When your project is live the costs for changing things later in the design will go up!

      • If you are using a baseclass implemented by a 3:rd party, consider "go up" one level instead of "overriding" with "NotImplementedException" or such. If there is no other level, consider design the code from scratch.

      • Always consider to seal classes you do not want anyone to be able to inherit it. It forces coders to "go up one level" in the "inheritance- hierarchy" and thus "loose ends" like "NotImplementedException" can be avoided.

    0 讨论(0)
  • 2020-11-27 20:38

    You can't, that's the whole point of inheritance: the subclass must offer all methods and properties of the base class.

    You could change the implementation to throw an exception when the property is called (if it were virtual)...

    0 讨论(0)
  • 2020-11-27 20:42

    I completely agree that properties should not be removed from base classes, but sometimes a derived class might have a different more appropriate way to enter the values. In my case, for example, I am inheriting from ItemsControl. As we all know, ItemsControl has the ItemsSource property, but I want my control to merge data from 2 sources (for example, Person and Location). If I were to have the user enter the data using ItemsSource, I would need to separate and then recombine the values, so I created 2 properties to enter the data. But back to the original question, this leaves the ItemsSource, which I do not want the user to use because I am "replacing" it with my own properties. I like the Browsable and EditorBrowsable ideas, but it still does not prevent the user from using it. The basic point here is that inheritance should keep MOST of the properties, but when there is a large complex class (especially ones where you cannot modify the original code), rewriting everything would be very inefficient.

    0 讨论(0)
  • 2020-11-27 20:44

    I smell a code smell here. It is my opinion that you should only inherit a base class if you're implementing all of the functionality of that base class. What you're doing doesn't really represent object oriented principles properly. Thus, if you want to inherit from your base, you should be implementing Name, otherwise you've got your inheritance the wrong way around. Your class A should be your base class and your current base class should inherit from A if that's what you want, not the other way around.

    However, not to stray too far from the direct question. If you did want to flout "the rules" and want to continue on the path you've chosen - here's how you can go about it:

    The convention is to implement the property but throw a NotImplementedException when that property is called - although, I don't like that either. But that's my personal opinion and it doesn't change the fact that this convention still stands.

    If you're attempting to obsolete the property (and it's declared in the base class as virtual), then you could either use the Obsolete attribute on it:

    [Obsolete("This property has been deprecated and should no longer be used.", true)]
    public override string Name 
    { 
        get 
        { 
            return base.Name; 
        }
        set
        {
            base.Name = value;
        }
    }
    

    (Edit: As Brian pointed out in the comments, the second parameter of the attribute will cause a compiler error if someone references the Name property, thus they won't be able to use it even though you've implemented it in derived class.)

    Or as I mentioned use NotImplementedException:

    public override string Name
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
    

    However, if the property isn't declared as virtual, then you can use the new keyword to replace it:

    public new string Name
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
    

    You can still use the Obsolete attribute in the same manner as if the method was overridden, or you can throw the NotImplementedException, whichever you choose. I would probably use:

    [Obsolete("Don't use this", true)]
    public override string Name { get; set; }
    

    or:

    [Obsolete("Don't use this", true)]
    public new string Name { get; set; }
    

    Depending on whether or not it was declared as virtual in the base class.

    0 讨论(0)
提交回复
热议问题