简体   繁体   English

C#继承隐藏继承的成员

[英]C# Inheritance to hide inherited Members

I read other threads like this but they didn't work for me. 我看了其他线程像这样 ,但他们并没有为我工作。

I got two classes: 我有两节课:

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.


}

If I now create a new object of ClassB I get 如果我现在创建一个ClassB的新对象,我得到

 _shouldBeInteger, _shouldBeBool, _shouldBeDateTime;
 shouldBeInteger,shouldBeBool,shouldBeDateTime

But I want to hide the _variables to the User. 但我想隐藏_variables给用户。 Setting them private in ClassB will override them, but I need to access them in order to parse there string values. 在ClassB中将它们设置为私有将覆盖它们,但我需要访问它们才能解析字符串值。

Update 更新

There is a ClassC filling ClassAs' values, which mainly is the reason why they have to be writeable. 有一个ClassC填充ClassAs的值,这主要是它们必须可写的原因。 There is no way for me to change the way that works, but I'm fully in Control of ClassA and ClassB 我没有办法改变它的工作方式,但我完全控制了ClassA和ClassB

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

Setting ClassA variables to private won't work, because programmer of ClassA produced it in a strange way. 将ClassA变量设置为private将不起作用,因为ClassA的程序员以一种奇怪的方式生成它。

Solution

Because ClassA needs to be writeable, but not readable to other classes than inheritated, I finally got this: 因为ClassA需要是可写的,但是对于继承的其他类不可读,我终于得到了这个:

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

which causes ClassB to work with theese properties, without giving them outside. 这会导致ClassB与theese属性一起使用,而不会将它们放在外面。 Intellisense still shows them, but you might consider using: Intellisense仍会显示它们,但您可以考虑使用:

 [EditorBrowsable(EditorBrowsableState.Never)]

to solve that. 解决这个问题。

Thanks to all. 谢谢大家。

I think you can solve your problem using: 我认为您可以使用以下方法解决问题:

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

so those variables are accessible to derived classes but not to user. 所以这些变量可以被派生类访问,但不能访问用户。

EDITED after user update: 用户更新后编辑:
I don't know if this could be a vali solution for you, but try: 我不知道这对你来说是否是一个vali解决方案,但请尝试:

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); }
    }
}

Inheritance can't hide the members as you would think. 继承不能像你想象的那样隐藏成员。 The new modifier exists to "hide" a base member, but that doesn't play nice when talking to base types. new修饰符用于“隐藏”基础成员,但在与基本类型交谈时不会很好。

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

You can either change the access level of the fields (the preferred way) or you can wrap the class instead of inheriting from it and provide simple pass-through methods to delegate to the wrapped class. 您可以更改字段的访问级别(首选方式),也可以包装类而不是继承它,并提供简单的传递方法来委托包装类。 This is called the Adapter Pattern : 这称为适配器模式

public class ClassB
{
    private ClassA _wrappedClass;
}

Just as an aside, your public fields are following the naming convention commonly used for private fields. 另外,您的公共字段遵循通常用于私有字段的命名约定。

The required access level for derived classes is protected . 派生类所需的访问级别protected If the members are used publicly but in the same assembly you can use protected internal . 如果成员是公开使用但在同一个程序集中,则可以使用protected internal If the members are used publicly by other assemblies... I'd suggest refactoring. 如果成员被其他程序集公开使用......我建议重构。

The problem is that you declared the fields public in the base class. 问题是您在基类中声明了字段public。 In order not to violate the polymorphic nature of inheritance, anything public in the base class must be public in all derived classes as well. 为了不违反继承的多态性,基类中的任何公共事物也必须在所有派生类中都是公共的。 If you could change that, you could never be sure that a ClassB could be passed to something expecting a ClassA. 如果你可以改变它,你永远不能确定ClassB可以传递给期望ClassA的东西。

Therefore, as other people have suggested, you probably want the base class fields to be declared protected, which is like private except derived classes can see them. 因此,正如其他人所建议的那样,您可能希望将基类字段声明为protected,这类似于private,但派生类可以看到它们。

However if you do need to access them via an actual instance of ClassA, you could declare them private and give them virtual public properties which the derived class can then override. 但是,如果您确实需要通过ClassA的实际实例访问它们,则可以将它们声明为private,并为它们提供虚拟公共属性,然后派生类可以覆盖它们。 This at least allows the derived class to change their behaviour, but it still can't actually hide them. 这至少允许派生类改变它们的行为,但它实际上仍然无法隐藏它们。

If that also doesn't fit, then it's probably worth considering using composition instead of inheritance because the substitution principle is actually getting in your way, and that's an inheritance fundamental. 如果这也不适合,那么可能值得考虑使用组合而不是继承,因为替换原则实际上妨碍了你的方式,这是继承的基础。

If you don't have control over ClassA, you'll need to create a wrapper/adapter class like so: 如果您无法控制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);
        }
    } 
}
public class ClassB
{
    private int shouldBeInteger;

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

}

OR 要么

  public class ClassB
  {

    public int ShouldBeInteger{ get; set; }

  }

In both of this case ShouldBeInteger will be accesible outside the class. 在这两种情况下,ShouldBeInteger都可以在课外访问。

In first case there were a private field, which cannot be accesible outside the class, 在第一种情况下,有一个私人领域,在课外无法访问,

values to private filed can be set through the public field. 私人领域的价值可以通过公共领域设定。

In second case the compiler automatically create a private backing field and do the same 在第二种情况下,编译器会自动创建一个私有支持字段并执行相同操作

process as above. 过程如上。 This is auto implemented property. 这是自动实现的属性。

Hope this may help you. 希望这可以帮到你。

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

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