C# 如何在不修改继承类(基类)的情况下隐藏类中的继承属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1875401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to hide an inherited property in a class without modifying the inherited class (base class)?
提问by Ahmed Magdy
If i have the following code example:
如果我有以下代码示例:
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA : ClassBase
{
public int JustNumber { get; set; }
public ClassA()
{
this.ID = 0;
this.Name = string.Empty;
this.JustNumber = string.Empty;
}
}
What should I do to hide the property Name
(Don't shown as a member of ClassA members) without modifying ClassBase
?
我应该怎么做才能在Name
不修改的情况下隐藏属性(不显示为 ClassA 成员的成员)ClassBase
?
采纳答案by BenAlabaster
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.
我在这里闻到了代码的味道。我的观点是,如果您要实现该基类的所有功能,您应该只继承该基类。你在做什么并没有真正正确地代表面向对象的原则。因此,如果你想从你的基础继承,你应该实现 Name,否则你的继承方式是错误的。你的类 A 应该是你的基类,如果这是你想要的,你当前的基类应该从 A 继承,而不是相反。
However,not to stray too far from the direct question. If you didwant 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.
约定是实现该属性,但在调用该属性时抛出 NotImplementedException - 尽管我也不喜欢那样。但这是我个人的意见,它并没有改变这个约定仍然存在的事实。
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 属性:
[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.)
(编辑:正如 Brian 在评论中指出的那样,如果有人引用 Name 属性,该属性的第二个参数将导致编译器错误,因此即使您已经在派生类中实现了它,他们也将无法使用它。 )
Or as I mentioned use NotImplementedException:
或者正如我提到的使用 NotImplementedException:
public override string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
However, if the property isn'tdeclared as virtual, then you can use the new keyword to replace it:
但是,如果该属性未声明为 virtual,则可以使用 new 关键字来替换它:
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 属性,或者您可以抛出 NotImplementedException,无论您选择哪种方式。我可能会使用:
[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.
取决于它是否在基类中被声明为虚拟的。
回答by Fried Hoeben
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)...
您可以更改实现以在调用属性时抛出异常(如果它是虚拟的)...
回答by Ryan Lundy
While technically the property won't be hidden, one way to strongly discourage its use is to put attributes on it like these:
虽然从技术上讲该属性不会被隐藏,但强烈阻止其使用的一种方法是将属性放在它上面,如下所示:
[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
This is what System.Windows.Forms does for controls that have properties that don't fit. The Textproperty, for instance, is on Control, but it doesn't make sense on every class that inherits from Control. So in MonthCalendar, for instance, the Text property appears like this (per the online reference source):
这就是 System.Windows.Forms 为具有不适合的属性的控件所做的。该文本属性,例如,是在控制,但它不会使每类继承的控制感。例如,在MonthCalendar 中, Text 属性如下所示(根据在线参考源):
[Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
get { return base.Text; }
set { base.Text = value; }
}
- Browsable- whether the member shows up in the Properties window
- EditorBrowsable- whether the member shows up in the Intellisense dropdown
- 可浏览- 成员是否显示在“属性”窗口中
- EditorBrowsable- 该成员是否出现在 Intellisense 下拉列表中
EditorBrowsable(false) won't prevent you from typing the property, and if you use the property, your project will still compile. But since the property doesn't appear in Intellisense, it won't be as obvious that you can use it.
EditorBrowsable(false) 不会阻止您键入该属性,并且如果您使用该属性,您的项目仍将编译。但是由于该属性没有出现在 Intellisense 中,因此您可以使用它就不会那么明显了。
回答by CCondron
Just hide it
把它藏起来
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA : ClassBase
{
public int JustNumber { get; set; }
private new string Name { get { return base.Name; } set { base.Name = value; } }
public ClassA()
{
this.ID = 0;
this.Name = string.Empty;
this.JustNumber = 0;
}
}
Note: Name will still be a public member of ClassBase, given the constraint of not changing the base class there is no way to stop that.
注意:Name 仍将是 ClassBase 的公共成员,鉴于不更改基类的约束,无法阻止它。
回答by flayn
Why force inheritance when it's not necessary? I think the proper way of doing it is by doing has-ainstead of a is-a.
为什么在不需要时强制继承?我认为正确的做法是做has-a而不是is-a。
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA
{
private ClassBase _base;
public int ID { get { return this._base.ID; } }
public string JustNumber { get; set; }
public ClassA()
{
this._base = new ClassBase();
this._base.ID = 0;
this._base.Name = string.Empty;
this.JustNumber = string.Empty;
}
}
回答by engnrman
I don't think a lot of the people replying here understand inheritance at all. There is a need to inherit from a base class and hide its once public var's and functions. Example, lets say you have a basic engine and you want to make a new engine that is supercharged. Well, 99% of the engine you will use but you will tweak a bit of its functionality to make it run much better and yet still there is some functionality that should only be shown to the modifications made, not the end user. Because we all know that every class MS puts out doesn't really ever need any modifications.
我认为在这里回复的很多人根本不了解继承。需要从基类继承并隐藏其曾经的公共变量和函数。例如,假设您有一个基本引擎,并且想要制造一个增压的新引擎。好吧,您将使用 99% 的引擎,但您将调整其功能以使其运行得更好,但仍然有一些功能应该只向所做的修改显示,而不是向最终用户显示。因为我们都知道 MS 推出的每个课程实际上都不需要任何修改。
Besides using the new to simply override the functionality it is one of the things that Microsoft in their infinite wis….. oh, I mean mistakes considered a tool not worthwhile anymore.
除了使用新来简单地覆盖功能之外,这是微软在其无限智慧中的一件事......哦,我的意思是错误被认为是一个不再值得的工具。
The best way to accomplish this now is multi-level inheritance.
现在实现这一目标的最佳方法是多级继承。
public class classA
{
}
public class B : A
{}
public class C : B
{}
Class B does all your work and class C exposes what you need exposed.
B 类完成您的所有工作,C 类公开您需要公开的内容。
回答by user3567581
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#.
好的设计是让基类共享某个概念所具有的共同属性(虚拟的或真实的)。示例:C# 中的 System.IO.Stream。
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.
尽量减少基类中的属性和方法的数量。如果您不希望在继承基类的类中使用某些属性或方法;那就不要把它放在基类中。如果您正处于项目的开发阶段;现在总是回到绘图板然后检查设计,因为事情发生了变化!需要时重新设计。当您的项目上线时,在设计后期更改内容的成本将会上升!
如果您使用的是由 3:rd 方实现的基类,请考虑“上升”一级,而不是使用“NotImplementedException”等“覆盖”。如果没有其他层次,可以考虑从头开始设计代码。
始终考虑密封您不希望任何人能够继承它的类。它强制编码人员在“继承层次结构”中“上升一级”,因此可以避免“无端”,例如“NotImplementedException”。
回答by Nane
I know that the question is old, but what you can do is override the PostFilterProperties like this:
我知道这个问题很老,但你可以做的是像这样覆盖 PostFilterProperties:
protected override void PostFilterProperties(System.Collections.IDictionary properties)
{
properties.Remove("AccessibleDescription");
properties.Remove("AccessibleName");
properties.Remove("AccessibleRole");
properties.Remove("BackgroundImage");
properties.Remove("BackgroundImageLayout");
properties.Remove("BorderStyle");
properties.Remove("Cursor");
properties.Remove("RightToLeft");
properties.Remove("UseWaitCursor");
properties.Remove("AllowDrop");
properties.Remove("AutoValidate");
properties.Remove("ContextMenuStrip");
properties.Remove("Enabled");
properties.Remove("ImeMode");
//properties.Remove("TabIndex"); // Don't remove this one or the designer will break
properties.Remove("TabStop");
//properties.Remove("Visible");
properties.Remove("ApplicationSettings");
properties.Remove("DataBindings");
properties.Remove("Tag");
properties.Remove("GenerateMember");
properties.Remove("Locked");
//properties.Remove("Modifiers");
properties.Remove("CausesValidation");
properties.Remove("Anchor");
properties.Remove("AutoSize");
properties.Remove("AutoSizeMode");
//properties.Remove("Location");
properties.Remove("Dock");
properties.Remove("Margin");
properties.Remove("MaximumSize");
properties.Remove("MinimumSize");
properties.Remove("Padding");
//properties.Remove("Size");
properties.Remove("DockPadding");
properties.Remove("AutoScrollMargin");
properties.Remove("AutoScrollMinSize");
properties.Remove("AutoScroll");
properties.Remove("ForeColor");
//properties.Remove("BackColor");
properties.Remove("Text");
//properties.Remove("Font");
}
回答by Nathan Sokalski
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.
我完全同意不应从基类中删除属性,但有时派生类可能有不同的更合适的方式来输入值。例如,就我而言,我是从 ItemsControl 继承的。众所周知,ItemsControl 具有 ItemsSource 属性,但我希望我的控件合并来自 2 个源(例如,Person 和 Location)的数据。如果我让用户使用 ItemsSource 输入数据,我需要将这些值分开然后重新组合,因此我创建了 2 个属性来输入数据。但是回到最初的问题,这留下了 ItemsSource,我不希望用户使用它,因为我正在用我自己的属性“替换”它。我喜欢 Browsable 和 EditorBrowsable 的想法,但它仍然不会阻止用户使用它。
回答by Abdus Salam Azad
You can use Browsable(false)
您可以使用Browsable(false)
[Browsable( false )]
public override string Name
{
get { return base.Name; }
set { base.Name= value; }
}