C# 如何在不修改继承的类(基类)的情况下隐藏类中的继承属性?
如果我有以下代码示例:C# 如何在不修改继承的类(基类)的情况下隐藏类中的继承属性?,c#,inheritance,properties,base-class,C#,Inheritance,Properties,Base Class,如果我有以下代码示例: 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
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;
}
}
我应该如何隐藏属性
Name
(不显示为ClassA成员的成员),而不修改ClassBase
?你不能,这就是继承的全部要点:子类必须提供基类的所有方法和属性
您可以将实现更改为在调用属性时引发异常(如果它是虚拟的).我在这里闻到了代码的味道。我认为,只有在实现基类的所有功能时,才应该继承该基类。您所做的并不能正确地表示面向对象的原则。因此,如果您想从基础继承,那么应该实现Name,否则您的继承方式就错了。你的类A应该是你的基类,你当前的基类应该继承自A,如果这是你想要的,而不是相反 但是,不要偏离直接的问题太远。如果你真的想藐视“规则”,想继续走你选择的道路——以下是你可以做到的: 约定是实现该属性,但在调用该属性时抛出NotImplementedException——尽管我也不喜欢这样。但这是我个人的观点,这并不能改变这个公约仍然存在的事实 如果您试图废弃该属性(并且该属性在基类中声明为虚拟属性),则可以对其使用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:正如Brian在评论中指出的,如果有人引用Name属性,该属性的第二个参数将导致编译器错误,因此即使您在派生类中实现了它,他们也无法使用它。)
或者,正如我提到的,使用NotImplementedException:
public override string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
但是,如果属性未声明为虚拟,则可以使用new关键字替换它:
public new string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
您仍然可以像重写方法一样使用过时属性,或者可以抛出NotImplementedException,无论您选择哪个。我可能会使用:
[Obsolete("Don't use this", true)]
public override string Name { get; set; }
或:
取决于它是否在基类中声明为虚拟。从技术上讲,该属性不会被隐藏,但强烈反对使用它的一种方法是在其上放置如下属性:
[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
这就是System.Windows.Forms对属性不合适的控件所做的。例如,Text属性位于控件上,但它对从控件继承的每个类都没有意义。例如,在中,文本属性如下所示(根据在线参考源):
- 可浏览-成员是否显示在属性窗口中
- EditorBrowsable-成员是否显示在Intellisense下拉列表中
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;
}
}
注意:Name仍然是ClassBase的公共成员,考虑到不更改基类的限制,没有办法阻止它。为什么在不需要继承时强制继承? 我认为正确的做法是做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;
}
}
我认为这里的很多人根本不理解继承。需要从基类继承并隐藏其曾经公开的var和函数。例如,假设你有一个基本的发动机,你想制造一个新的增压发动机。好吧,99%的引擎你会使用,但你会调整一点它的功能,使其运行得更好,但仍然有一些功能,应该只显示给修改,而不是最终用户。因为我们都知道MS推出的每个类实际上并不需要任何修改 除了使用新功能来简单地覆盖功能之外,这也是微软在其无限智慧中所做的事情之一…。。哦,我的意思是错误被认为不再是一种值得使用的工具 现在实现这一点的最佳方法是多级继承
public class classA
{
}
public class B : A
{}
public class C : B
{}
B类完成您的所有工作,C类公开您需要公开的内容 我认为如果必须这样做,那么设计就很糟糕,尤其是如果你能够从头开始设计代码的话 为什么? 好的设计是让基类共享某个概念具有的公共属性(虚拟或真实)。示例:C#中的System.IO.Stream 再往下走,糟糕的设计将增加维护成本,使实施变得越来越困难。尽量避免这种情况 我使用的基本规则:
- 最小化基类中属性和方法的数量。如果您不希望在继承基类的类中使用某些属性或方法;那么不要把它放在基类中。如果您处于项目的开发阶段;总是回到绘图板上,然后检查设计,因为事情发生了变化!需要时重新设计。当你的项目是活的成本为改变东西在以后的设计将上升
>P>如果您使用的是由3:RD党实现的BaseCLASS,请考虑“上行”一个级别,而不是“NoTimPrimeNeTestExpCup”的“覆盖”。如果没有其他级别,请考虑从头开始设计代码。
总是考虑密封类,你不希望任何人能够继承它。它迫使编码人员在“继承层次结构”中“上一级”,因此可以避免像“NotImplementedException”这样的“松散结尾”
- 我知道这个问题很老了,但是w
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;
}
}
public class classA
{
}
public class B : A
{}
public class C : B
{}
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");
}
[Browsable( false )]
public override string Name
{
get { return base.Name; }
set { base.Name= value; }
}