C#继承隐藏继承的成员

时间:2012-01-19 09:26:56

标签: c# .net oop class object

我读过this之类的其他帖子,但它们对我没用。

我有两节课:

public class ClassA 
{
    public string _shouldBeInteger;
    public string _shouldBeBool;
    public string _shouldBeDateTime;
}

public class ClassB : ClassA
{
   public int? shouldBeInteger
    {
        get { return (_shouldBeInteger != null) ? Convert.ToInt32(Convert.ToDouble(_shouldBeInteger)) : new int?(); }
        set { _shouldBeInteger = Convert.ToString(value); }
    } 

  //... same thing with datetime etc.


}

如果我现在创建一个ClassB的新对象,我得

 _shouldBeInteger, _shouldBeBool, _shouldBeDateTime;
 shouldBeInteger,shouldBeBool,shouldBeDateTime

但我想隐藏_variables给用户。 在ClassB中将它们设置为私有将覆盖它们,但我需要访问它们才能解析字符串值。

更新

有一个ClassC填充ClassAs'价值观,这主要是他们必须可写的原因。我没办法改变它的工作方式,但我完全控制了ClassA和ClassB

ClassC //not changeAble for me
{
 //infomagic filling values of ClassA    
}

将ClassA变量设置为私有无法工作,因为ClassA的程序员以一种奇怪的方式生成它。

解决方案

因为ClassA需要是可写的,但除了继承之外不能读取其他类,我终于明白了:

ClassA 
{ 
  public string _shouldBeInteger { protected get; set; } 
  //and so on
} 

导致ClassB与theese属性一起使用,而不将它们放在外面。 Intellisense仍会显示它们,但您可以考虑使用:

 [EditorBrowsable(EditorBrowsableState.Never)]

解决这个问题。

感谢所有人。

5 个答案:

答案 0 :(得分:9)

我认为您可以使用以下方法解决问题:

public class ClassA 
{
    protected string _shouldBeInteger;
    protected string _shouldBeBool;
    protected string _shouldBeDateTime;
}

因此派生类可以访问这些变量,但不能访问用户。

用户更新后编辑:
我不知道这对你来说是否适合你,但请尝试:

public class ClassB : ClassA
{
    public new int? _shouldBeInteger
    {
        get { return (base._shouldBeInteger != null) ?
                     Convert.ToInt32(Convert.ToDouble(base._shouldBeInteger)) : 
                     new int?(); }
        set { base._shouldBeInteger = Convert.ToString(value); }
    }
}

答案 1 :(得分:4)

继承不能像你想象的那样隐藏成员。 new修饰符存在以“隐藏”基本成员,但在与基本类型交谈时这不会很好。

http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

您可以更改字段的访问级别(首选方式),也可以包装类而不是继承它,并提供简单的传递方法来委托包装类。这称为Adapter Pattern

public class ClassB
{
    private ClassA _wrappedClass;
}

除此之外,您的公共字段遵循通常用于私有字段的命名约定。

派生类所需的访问级别为protected。如果成员公开使用但在同一个程序集中,您可以使用protected internal。如果成员被其他程序集公开使用......我建议重构。

答案 2 :(得分:1)

问题是您在基类中声明了字段public。为了不违反继承的多态性,基类中的任何公共事物也必须在所有派生类中都是公共的。如果你可以改变它,你永远不能确定ClassB可以传递给期望ClassA的东西。

因此,正如其他人所建议的那样,您可能希望将基类字段声明为protected,这类似于私有,除了派生类可以看到它们。

但是,如果您确实需要通过ClassA的实际实例访问它们,则可以将它们声明为private,并为它们提供虚拟公共属性,然后派生类可以覆盖它们。这至少允许派生类改变它们的行为,但它实际上仍然无法隐藏它们。

如果这也不适合,那么可能值得考虑使用组合而不是继承,因为替换原则实际上是妨碍了你的方式,这是继承的基础。

答案 3 :(得分:0)

如果您无法控制ClassA,您需要创建一个包装器/适配器类,如下所示:

public class ClassB
{
    private readonly _classA = new ClassA();

    public int? shouldBeInteger
    {
        get
        {
            return (this._classA._shouldBeInteger != null)
                ? Convert.ToInt32(Convert.ToDouble(this._classA._shouldBeInteger))
                : new int?();
       }
        set
        {
            this._classA._shouldBeInteger = Convert.ToString(value);
        }
    } 
}

答案 4 :(得分:0)

public class ClassB
{
    private int shouldBeInteger;

    public int ShouldBeInteger
    {
        get { return shouldBeInteger; }
        set { shouldBeInteger = value; }
    }

}

OR

  public class ClassB
  {

    public int ShouldBeInteger{ get; set; }

  }

在这两种情况下,ShouldBeInteger都可以在课堂外访问。

在第一种情况下,有一个私有字段,无法在课堂外访问,

私人领域的价值可以通过公共领域设定。

在第二种情况下,编译器会自动创建一个私有支持字段并执行相同的操作

如上所述的过程。这是自动实现的属性。

希望这可以帮助你。