2

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

 _shouldBeInteger, _shouldBeBool, _shouldBeDateTime;
 shouldBeInteger,shouldBeBool,shouldBeDateTime

But I want to hide the _variables to the User. Setting them private in ClassB will override them, but I need to access them in order to parse there string values.

Update

There is a ClassC filling ClassAs' values, which mainly is the reason why they have to be writeable. There is no way for me to change the way that works, but I'm fully in Control of ClassA and 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.

Solution

Because ClassA needs to be writeable, but not readable to other classes than inheritated, I finally got this:

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

which causes ClassB to work with theese properties, without giving them outside. Intellisense still shows them, but you might consider using:

 [EditorBrowsable(EditorBrowsableState.Never)]

to solve that.

Thanks to all.

Community
  • 1
  • 1
Harry
  • 1,313
  • 3
  • 22
  • 37
  • when you said setting the fields private won't work, do they need to be public or will protected work? – Adam Houldsworth Jan 19 '12 at 09:35
  • the underscore prefix is a standard for `private members`, not `public members` – gdoron Jan 19 '12 at 09:35
  • Just to nitpick on @gdoron's comment, underscore prefix is not compliant with CLS and so not standard, but private members are not a concern for CLS compliance. Hence they're allowed and have the advantage that if you moved something private to public while exploring an issue the CLS compliance warning will flag that it's not in a good state for final release. – Jon Hanna Jan 19 '12 at 09:45
  • "because programmer of ClassA produced it in a strange way" - damn right he did! – MattDavey Jan 19 '12 at 09:49
  • @JonHanna this is a good point. .NET languages are not guaranteed/required to support member names with a leading underscore. Although I'm not aware of any .NET languages which don't. – MattDavey Jan 19 '12 at 09:50
  • Thanks so far, I'm trying to explain the situation the best way I can with my Update. What about private getters and public setters for classA? I can't imagine this would help ClassB to hide theese fields, any advice? – Harry Jan 19 '12 at 09:53
  • you can't change `ClassC`, I understand? Is it external? Is it written from someone else? – Marco Jan 19 '12 at 09:58
  • Its internal, written by someone else and companys daily tool, way to big to change it. I just can "put something between" ClassC and ClassA by inheritate somthing (ClassB) – Harry Jan 19 '12 at 10:02
  • @Harry How does ClassC expect to access the fields? I am assuming reflection or code-gen here. – Adam Houldsworth Jan 19 '12 at 10:19
  • I suppose its filling by reflection expecting every property to be string. It would be much better, the original programmer would have casted things there - actually I went to him a minute ago, asked him exactly that, he said, he didn't do it there cause of performance reasons... but, whatever. For now, I really like the solution, we found cause of your help! – Harry Jan 19 '12 at 10:42

5 Answers5

9

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:

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); }
    }
}
Marco
  • 56,740
  • 14
  • 129
  • 152
  • Can someone explain why a downvote? What's wrong with my answer? – Marco Jan 19 '12 at 09:35
  • +1 Not sure, aside from possibly the field names, making them protected is a valid solution. Unless they are required to be public but the OP hasn't said that. – Adam Houldsworth Jan 19 '12 at 09:37
  • sry downvoted because I got the impression from the question that he doesn't have control over ClassA. If that's not the case I'll undownvote :) – MattDavey Jan 19 '12 at 09:39
  • @MattDavey: he told nothing about that... or I'm quite sure OP didn't tell us. Anyway ok, I accept downvotes when there is a reason for them! :) – Marco Jan 19 '12 at 09:40
  • My interpretation of the last sentence in the question was that the OP didn't want to or couldn't change ClassA for unspecified reasons - I guess there are lots of ways to interpret that sentence though. Downvote wasn't intended to say your answer was wrong, just that it wasn't workable in my interpretation of the OPs scenario.. :) – MattDavey Jan 19 '12 at 09:47
  • I need ClassA be writeable for classC, I'm in control of ClassA and can make changes. Cuz of ClassC is non inhiterated from ClassA, protected won't wrok here. (Update) Sorry i left this out @Marco – Harry Jan 19 '12 at 09:55
  • @Harry: take a look at my edited answer and tell me what do you think – Marco Jan 19 '12 at 10:11
  • @Marco I like the Idea, but ClassC still tries to fill ClassA/ClassB with Strings and throws AmbiguousMatchException. In this case it won't help, but its a nice way I will keep in mind! Tanks – Harry Jan 19 '12 at 10:28
  • @Marco I really want to accept your, cuz you brought me to this: `ClassA { public string _shouldBeInteger { protected get; set; } }` which causes ClassB not to give theese further. With `[EditorBrowsable(EditorBrowsableState.Never)]` they are even hidden from intellisense. Thanks a lot! – Harry Jan 19 '12 at 10:32
  • @Marco I weren't sure, because another User needs to read the comments to find the way i finally solved it.. :) But hey – Harry Jan 19 '12 at 10:51
  • @Harry: the best solution is you edit your question appending a **SOLUTION** part, so everyone can read it directly! ;) – Marco Jan 19 '12 at 10:52
  • In early versions of the .NET Framework, protected member names with leading underscores were reserved for use by some of the internal libraries. As a consequence, inheriting and overriding such members was not guaranteed to work and, from practical experience, values would sometimes be inaccessible. Since then, I've adopted the convention of using a trailing underscore for such members and .NET has had no problem with it. – Suncat2000 Dec 19 '13 at 13:20
4

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.

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. If the members are used publicly but in the same assembly you can use protected internal. If the members are used publicly by other assemblies... I'd suggest refactoring.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • 1
    Watching at OP update I edited my answer: what do you think? Could it be a way out? – Marco Jan 19 '12 at 10:12
  • Wrapping the class.. Surely possible. Found another way now, but next time i will think about that earlier. Thanks. – Harry Jan 19 '12 at 10:36
1

The problem is that you declared the fields public in the base class. 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.

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.

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. 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.

Matthew Walton
  • 9,809
  • 3
  • 27
  • 36
0

If you don't have control over ClassA, you'll need to create a wrapper/adapter class like so:

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);
        }
    } 
}
MattDavey
  • 8,897
  • 3
  • 31
  • 54
  • 1
    Don't use `ClassA` for an internal class name... it's better something `private classA = new ClassA();` :) – Marco Jan 19 '12 at 09:39
  • @Marco you're right, originally it was a private property but I changed it to a field at the last minute :) – MattDavey Jan 19 '12 at 09:52
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; }

  }

In both of this case ShouldBeInteger will be accesible outside the class.

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.

Anoop K
  • 56
  • 7