From: Peter Duniho on
JAM wrote:
> On Jan 31, 10:36 pm, Peter Duniho <no.peted.s...(a)no.nwlink.spam.com>
> wrote:
>> That's correct. To access a protected member of a base class, your
>> class has to access that protected member via a variable of its own type.
>>
>> Consider the alternative: if you could start accessing protected members
>> of _any_ instance of a class A just by inheriting A and doing it from
>> the sub-class, then accessibility protection would be basically
>> meaningless. You could bypass it anytime you want just by inheriting
>> the class you want to get at.
>
> Sure, but I would do it on purpose so the assumption would be that I
> know what I'm doing. I don't see the alternative as being so bad here.

OOP encapsulation rules are predicated on the assumption that any code
other than the code in the class is not written by someone who "knows
what they're doing".

If you would prefer to work without the constraints that these language
rules provide, you probably would prefer to work in a different
language. Alternatively, if you insist that you always "know what
you're doing", why not just make everything in the class public. Then
you have complete access, and don't have to worry about the compiler
looking over your shoulder every time you want to do something. :)

Not something I'd advise personally. But you can do it that way if you
find the rules too constraining.

>> Note that if your "items" variable was a "List<B>", the access would
>> have been just fine. That's because the class B is trusted to access
>> protected members in instances of itself.
>
> But that actually would make my program less self explanatory.

Uh, not really. Not within the constraints of the C# language.

> In my
> program class A is a node in the tree structure.
> Class B is a root node of that tree. B requires slightly different
> handling than A, that is why it is derived from A.
> The list is a list of subnodes. It would make akward reading if the
> list would be a list of rootnodes.

If you can't guarantee that the elements in the list are of type B, then
IMHO your code has no business accessing protected members of the
instances in the list from code in class B.

If you _could_ guarantee the elements are of type B (sounds like you
can't, but speaking hypothetically), then of course using type B in the
list is more "self-explanatory".

> Function F in my program simply
> opens particular branch (recursively) from data file. However root
> node cannot use F to open itself. It uses different function. But then
> it opens it's entire branch using F for all it's subnodes from the
> list. There is no reason for F to be used anywhere else. That is why I
> tought it would be a good idea to hide it from public interface.

It's hard to speak of specifics without specific code. But having
written various tree-based UIs myself, including those linked to data
files and to file system structures, I can safely say that having your
tree made up of different kinds of nodes depending on their location
within the tree is a highly unusual, and highly suspect, design.

This is in fact consistent with my more general observation I mentioned
before: if you find yourself fighting the language, you've probably made
a design error somewhere.

This might be the design error you've made: having two different node
types in the same tree, at least as far as the tree itself is concerned
(of course, one can imagine a tree structure with varying node types,
but they would all inherit the same base class, and the code dealing
with the tree would only care about that base class, not all the various
sub-class types).

> [...]
>>> Do I have to expose F as public to be able to access it when
>>> particular A is not a base for this particular B but when the A
>>> belongs somehow to this particular B which has some different A as
>>> base ?
>> That sentence is pretty awkward.
>
> Sorry. English is not my first language.

Well, then your sentence is surprisingly well constructed. :)
(Seriously, I never would have guessed English isn't your first
language, so you're doing way better than many native speakers of
English :) ).

> [...]
>> But as a general rule, yes�if you have a member in one class that you
>> want to be accessible via code not in an instance of the class in which
>> the member is defined, that member has to be public.
>
> Well, then I think my particular case proves that C# in rare
> situations is lacking more granular access control that would be
> usefull.

Personally, I think your particular case proves that you could improve
your design. :)

>> I would furthermore argue that if you find yourself trying to design a
>> class to the contrary of this, that you've made a mistake in the program
>> design.
>
> What you think about my example ? In my experinece with tree
> structures it often happens that root node has slightly different
> needs that other nodes.

I've written hundreds of tree structures in my career, and have never
had to have a root node be a different type or handled differently than
the other nodes.

I would be happy to try to offer more specific advice if you can provide
more details of your problem. But I do believe that you can solve your
problem quite well and elegantly without violating C#'s access rules,
and even without using "internal" as your access modifier.

Pete
From: JAM on
On Feb 1, 2:19 pm, Peter Duniho <no.peted.s...(a)no.nwlink.spam.com>
wrote:

> OOP encapsulation rules are predicated on the assumption that any code
> other than the code in the class is not written by someone who "knows
> what they're doing".

Knows in a sense that since B is derieved from A my guess was that it
should see protected members of A even if A is not the base instance
of B. Obviously I was wrong, but I don't fully understand the reason
for this restriction. When I construct B derieved from A I expect B to
see protected members of it's base class. What makes it so different
if instance of A is not a base for particular B ? The author of class
A by making function "protected" already assumed that author of B will
eventually be allowed to use it and in order to use it must assume
responsibility for using it properly.

> It's hard to speak of specifics without specific code.  But having
> written various tree-based UIs myself, including those linked to data
> files and to file system structures, I can safely say that having your
> tree made up of different kinds of nodes depending on their location
> within the tree is a highly unusual, and highly suspect, design.

I think you are too judgmental. This is not as "unusual" as you
suggest. Windows file system is a good example of such tree. The root
node is a disk drvie whereas nodes of the tree are directories. I do
realize that in fact behind "disk drive" is really root directory of
the drive, but still it makes easier to consider root node as
different from others. There is substantial amount of functionality
that applies to disk drive but is not applicable to some directory on
that drive. Windows 7 added Libraries, which probably need another
node type to distinguish them from conventional directory so one can
imagine even more rich tree. Windows Explorer also introduces node
callled "MyComputer" - the very top node of the entire tree which is
neither a disk drive nor directory and none of typical directory or
disk functions apply to it.

> I would be happy to try to offer more specific advice if you can provide
> more details of your problem.  But I do believe that you can solve your
> problem quite well and elegantly without violating C#'s access rules,
> and even without using "internal" as your access modifier.

My tree is similar to the one mentioned for Windows Explorer. It has
root node that has some of the functionality of subnodes but also has
much more additional functionality and stores additional information
It is always predefined to reside as the root. Every other node in the
tree is of the other class type and does not need extended
functionality or storage. It seemed usefull to make B root node and A
other nodes where B : A.

>
> Pete

From: Peter Duniho on
JAM wrote:
> On Feb 1, 2:19 pm, Peter Duniho <no.peted.s...(a)no.nwlink.spam.com>
> wrote:
>
>> OOP encapsulation rules are predicated on the assumption that any code
>> other than the code in the class is not written by someone who "knows
>> what they're doing".
>
> Knows in a sense that since B is derieved from A my guess was that it
> should see protected members of A even if A is not the base instance
> of B. Obviously I was wrong, but I don't fully understand the reason
> for this restriction.

Okay�maybe I wasn't careful enough in my previous explanation. I'll try
again�

> When I construct B derieved from A I expect B to
> see protected members of it's base class.

I would like you to try to consider why class A has protected members in
the first place, rather than just private and public, and given that why
class B should have access to protected members in class A.

Here's _my_ answer to that: the protected members are there to support
inheritance that allows the derived class to manipulate or otherwise use
those members. You can't allow that access for private members, because
then you can't design classes that have implementation details that are
hidden even from derived classes. And obviously you don't want those
details to be public, because that's implementation, not interface.

So we have protected. But it's there to support inheritance. As such,
they should be visible only to the class that has inherited them. So,
code in class B does have access to protected members. But only in
instances of class B, because that's the only class that should have
access to _any_ hidden members of class B.

If that doesn't seem to help explain it, consider this: the usage of a
protected member is defined by the class in which its contained. Once
class B is permitted to inherit a protected member, it gets to impose
its own usage rules on the protected members.

But, class B does not have any specific knowledge regarding how any
other class might use that member.

For example:

class Temperature
{
public int Value
{
get { return _temp; }
set { _temp = value; }
}

protected int _temp;
}

class Fahrenheit : Temperature
{
public int Celsius { get { return (_temp - 32) * 5 / 9; } }
}

class Celsius : Temperature
{
public int Fahrenheit { get { return _temp * 9 / 5 + 32; } }
}

Now, ignoring for a moment that classes designed like that are probably
not a good idea for other reasons, how is the Celsius class supposed to
successfully use the variable _temp found in instances of Temperature
that are not known to be also instances of Celsius?

> What makes it so different
> if instance of A is not a base for particular B ? The author of class
> A by making function "protected" already assumed that author of B will
> eventually be allowed to use it and in order to use it must assume
> responsibility for using it properly.

But only in the context of the inheriting class.

Frankly, I think protected members should be generally avoided, and this
is ten times more true IMHO for variables. Even between base and
derived classes, hiding implementation is a very good thing.

But, inasmuch as there may be a need to share implementation between the
base class and the derived class, there's no way to ensure in the design
of the code that when one derived class accesses a protected member that
is actually a member of a completely different derived class, that it's
doing so in a way that is consistent with the first derived class's
understanding of the member.

Thus, that's simply not allowed.

>> It's hard to speak of specifics without specific code. But having
>> written various tree-based UIs myself, including those linked to data
>> files and to file system structures, I can safely say that having your
>> tree made up of different kinds of nodes depending on their location
>> within the tree is a highly unusual, and highly suspect, design.
>
> I think you are too judgmental.

People who receive criticisms that they are unprepared to hear often
think that. Sorry about that. I do not intend to be judgmental, except
with respect to judging the _code_ and its design. Please don't take it
personally.

> This is not as "unusual" as you suggest.

I have enough experience in the area for me to confidently say that it is.

> Windows file system is a good example of such tree.

It's not, actually. Not in the sense that it supports the design you
seem to be working with.

> The root
> node is a disk drvie whereas nodes of the tree are directories.

Okay, let's take that abstraction as granted. We still cannot conclude
that there's any good reason for a node of one type to access a
protected member found in a node of another type.

Why should a node representing a drive have access to otherwise-private
members in a node not representing a drive? Or vice a versa? If that
member is protected, it's because the derived class is expected to do
something special with it. Something special that is not shared in
common with every class that inherits the base class.

If the derived class is not doing anything special with the protected
member, then that means the member should not have been marked as
protected in the first place. It should have been private, with all of
the general-purpose implementation in the base class.

Or, looking at your example from a slightly different point of view: as
far as the _tree_ structure is concerned, the shared base class that
describes the tree is the only important thing. Any code related to the
management of the tree itself should not care whether the node
represents a drive or a directory within a drive. And inasmuch as any
code is specific to one type of node or the other, that code should
operate only on the type of node in which that code exists.

> [...]
> My tree is similar to the one mentioned for Windows Explorer. It has
> root node that has some of the functionality of subnodes but also has
> much more additional functionality and stores additional information
> It is always predefined to reside as the root. Every other node in the
> tree is of the other class type and does not need extended
> functionality or storage. It seemed usefull to make B root node and A
> other nodes where B : A.

Been there, done that, and having done that I know for sure you don't
need a design in which a protected member is accessible from without the
class actually inheriting that member.

Pete
From: JAM on
On Feb 1, 6:39 pm, Peter Duniho <no.peted.s...(a)no.nwlink.spam.com>
wrote:

> JAM wrote:

> ...
> If that doesn't seem to help explain it, consider this: the usage of a
> protected member is defined by the class in which its contained.  Once
> class B is permitted to inherit a protected member, it gets to impose
> its own usage rules on the protected members.
>
> But, class B does not have any specific knowledge regarding how any
> other class might use that member.

This is what I don't fully get. I don't see the difference between
base instance and some other instance. If I can abuse protected member
of A when A is not base instance of B, then I can certainly make the
same abuse by incorrectly using protected member of A in B when A is a
base instance of B.

> For example:
>
>    class Temperature
>    {
>      public int Value
>      {
>        get { return _temp; }
>        set { _temp = value; }
>      }
>
>      protected int _temp;
>    }
>
>    class Fahrenheit : Temperature
>    {
>      public int Celsius { get { return (_temp - 32) * 5 / 9; } }
>    }
>
>    class Celsius : Temperature
>    {
>      public int Fahrenheit { get { return _temp * 9 / 5 + 32; } }
>    }
>
> Now, ignoring for a moment that classes designed like that are probably
> not a good idea for other reasons, how is the Celsius class supposed to
> successfully use the variable _temp found in instances of Temperature
> that are not known to be also instances of Celsius?

Well. Consider the opposite. If you have instance of Celsius, how
usage of base._temp makes it any different ? If author of Celsius has
no idea, of what exactly _temp does and how is used in Temperature,
why would author of B be any safer of using _temp in valid code case
when he is accessing it from the instance of B ? Also consider, that
in my problem I was not attempting to use protected member of class A
but I was attempting to execute protected member of the instance of
class A from within class B. The only difference was, that that
instance of A was not a base instance of calling B.

From the purity standpoint I can see your point that protected just
works this way as designed (which I did not know) and possibly has
some value. However my point is, that I see a value in my approach too
however rare. Maybe some other that public, protected or private
modifier would be needed to clarify this different approach.

> But only in the context of the inheriting class.
>
> Frankly, I think protected members should be generally avoided, and this
> is ten times more true IMHO for variables.  Even between base and
> derived classes, hiding implementation is a very good thing.

I agree but there are times when it is the simplest approach. My
problem is, that I was forced to use public in A. In my opinion I
ended up with more polluted code. Now the damn function is visible to
every class and it was only needed to be visible in B

> Okay, let's take that abstraction as granted.  We still cannot conclude
> that there's any good reason for a node of one type to access a
> protected member found in a node of another type.

You proof is circular. If there is no reason to access protected
member the member would be private. If the member if protected, there
must be a value in accessing it from class that inherits. And since
class that inherits can access it, it must do it correctly or the code
will produce garbage whether accessed class is a base instance or not.
The whole discussion is about value of accessing protected member. At
least one value is that when I use code completion, protected
functions will not show up in the list so I can't use them by
laziness. By forcing me to make function in A public in my specific
case, now I see the damn function every time I code something for A or
B and that was not my intent.

> Been there, done that, and having done that I know for sure you don't
> need a design in which a protected member is accessible from without the
> class actually inheriting that member.

With all do respect I agree to disagree here.

>
> Pete

JAM
From: Family Tree Mike on
JAM,

So take the following classes:

class A
{
protected void F() {}
}

class B : A
{
public List<A> items;

public void B()
{
items[0].F(); // <-- This does not generate an error
}
}

class C
{
public List<A> items;
public void C()
{
items[0].F(); // <-- This generates an error
}
}

You view the line in class B is acceptable only because the instance of
A (items [0]) is accessed from a subclass of A? But you also feel that
in class C, this would be illegal as C is not subclassing A, even though
it (items [0]) is still an instance of an A?

I'd hate to think about diagnosing that code later, among other
nightmares...

--
Mike