Reputation: 1
public class _base
{
protected int x = 5;
protected int GetX(_base b) { return b.x; }
}
public class _derived : _base
{
public int Foo()
{
var b = new _base();
//return b.x; // <-- this would be illegal
return GetX(b); // <-- This works and does exactly the same as the line above
}
}
(Please don't change code. It is working and shows the problem.)
The error is
Cannot access protected member '_base.x' via a qualifier of type '_base'; the qualifier must be of type '_derived' (or derived from it)
Note that because b is of type _base and we are not in base we cannot access it's protected members. I imagine the reason is because _base might be of some other derived type and hence it is not protecting the code but that's not the point. What I'm doing is creating a work around for the above problem using the extra protected methods. This gives me the behavior I want and the protection I want. I wish there were a keyword that allows this kinda access but there isn't. What I'm interested in is if this "pattern" has a name.
(I'm using protected because internal allows anyone in the same assembly access)
Upvotes: 4
Views: 280
Reputation: 486
Generally this sort of access is not allowed because the access modifiers work on classes(as meta access attributes). In your derived class, an instance of your base class has no class relation to the derived class. Here we are mixing instances and classes. The protected keyword offers only access to derived classes but from any instance(even if in a derived class).
It's obviously a deficit in the language but since 99.9% of the time it is not used it is not needed. In any case there is no keyword in C# that will offer what you want.
Upvotes: 3
Reputation: 660004
UPDATE: Rewriting this answer since the question has been rewritten.
I'm unaware of any name for the pattern you've illustrated.
As you conjecture, the reason it is illegal to access the field is because we don't know that the instance b is an instance of _derived. "protected" access means that _derived is only allowed to access protected members of instances of _derived; it is not allowed access to protected members of instances of "SomeOtherType" that is also derived from _base.
Now, if the question really is "is there any way to get direct access to the member x from every derived class through any instance?" then yes. You reject the obvious solution of making it internal. (*) There is another way. Do this:
abstract class B
{
private B() {}
private int x;
private class D1 : B { }
private class D2 : B { }
public static B MakeD1() { return new D1(); }
public static B MakeD2() { return new D2(); }
}
Now methods of B and methods of derived classes D1 and D2 are all capable of accessing this.x
directly, but methods of no other types are capable of doing so. There are no other derived types other than D1 and D2; there cannot be because the only constructor of B is private. And there cannot be any instances of B that are not D1 or D2 because it is abstract.
(*) Remember, if you make it internal then the only people you have to worry about accessing your member are your coworkers. Putting the smack down on them in code review if they do something abusive to the member is a perfectly acceptable solution around here.
Upvotes: 2
Reputation: 4751
I think I understand what you mean. Do not create base class' instances in methods. It gets created by the constructor. Reference base class members either using only the member name or you case precede it with the base keyword.
In the above example you would use it as follows:
class A : _base {
void Foo() {
x = 10; //or base.x = 10;
SetX(10); //or base.SetX(10);
Console.WriteLine(GetX()); //or base.GetX()
}
}
Moreover you may be interested in Properties construct which is a nice syntactic sugar for java's ugly getX and setX pattern.
Upvotes: 0
Reputation: 1618
Encapsulation.
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
Basically you control who has access to the members via accessors ("setters" and "getters"). How the underlying data is layed out remains hidden to the user.
Think of this:
If you would like to rename your X variable (for whatever reasons) in your base class, but there exists 100 classes derived from that base class who accessed it directly.
You would break that code.
class derived
{
void DoSomething() { x += 1; } // x renamed, doesn't compile anymore
}
Now, with encapsulation, since x cannot accessed directly, we got accessors:
class derived
{
void DoSomething() { SetX(GetX() + 1); } // No prob!
}
Upvotes: 0