Reputation: 3018
I have the following classes:
public class Essentials
{
public void DoSomething()
{
//doing base stuff...
}
}
public class NetworkEssentials : Essentials
{
public void DoNetworkSomething()
{
//doing something
}
}
public class someClass : NetworkEssentials
{
public void DoSomeSomething()
{
base.DoSomething(); //The thing I would like to prevent, as to block this from happening.
//attention: i dont want to change methods names so it will call the first parent, i still want to maintain a different method names to each class type
}
}
I want to prevent someClass
from being able to invoke methods in its parent's parent, only allowing direct inherit classes to invoke its base methods.
Is there anyway to do it?
Additional explanation:
basically, i have some mandatory fields i require that each object have, but there are some objects, not all, i demand to have an extra mandatory field. lets call them 1 2 3 , whereas 1 is the top parent. i want class 3 to call a class 2 method and this class 2 method will call the class 1 method, because only class 2 have this "extra" field. class 1 cant handle with this field because it doesnt recognize it at all
Upvotes: 3
Views: 2348
Reputation: 113242
You could use internal
and have NetworkEssentials
in the same assembly. (While .NET does have an access type for the intersection of internal
and protected
, which would be perfect here, C# does not, so you'll have to make do with internal
[Update: As of C# 7.2 there is now private protected
to use that intersection]).
You could have:
public class NetworkEssentials : Essentials
{
new protected void DoSomething()
{
throw new InvalidOperationException();
}
}
So the DoSomething
is hidden as far as the child goes. (It can't be public in Essentials
or else someClass
can see it the same as any other code).
It is still possible to get to DoSomething
with some convoluted approaches though, and it doesn't provide a compile-time block.
basically, i have some mandatory fields i require that each object have, but there are some objects, not all, i demand to have an extra mandatory field. lets call them 1 2 3 , whereas 1 is the top parent. i want class 3 to call a class 2 method and this class 2 method will call the class 1 method, because only class 2 have this "extra" field. class 1 cant handle with this field because it doesnt recognize it at all
Well, solve that problem then. If NetworkEssentials
knows how to call DoSomething()
correctly, just override DoSomething()
appropriately:
public class Essentials
{
public virtual void DoSomething()
{
//Do stuff with field 1
}
}
public class NetworkEssentials : Essentials
{
public override void DoSomething()
{
base.DoSomething(); // handle field 1
// Code to handle other fields either here, before the call to base.DoSomething(), or both.
}
}
Don't attempt to block calls to DoSomething()
, but use virtual methods to ensure they do the right thing. This is necessary anyway because non-inheriting code calling DoSomething()
still needs the correct behaviour.
Upvotes: 5
Reputation: 32750
I'm not sure what the issue is. Can't you solve this with plain old virtual and overriden methods?
public class Essentials
{
public virtual void DoSomething()
{
//do what needs to be done at this level
}
}
public class NetworkEssentials : Essentials
{
public override void DoSomething()
{
//do what needs to be done at this level
base.DoSomething(); //launch what needs to be done at Essentials' level.
}
}
public class someClass : NetworkEssentials
{
public override DoSomething()
{
//do what needs to be done at this level
base.DoSomething(); //launch what needs to be done at NetworkEssentials' level.
}
}
Note that this way, the derived class can only call it's parent's implementation. There is no way you could skip a level in the hierarchy and get SomeClass
to directly call Essentials.DoSomething
bypassing NetworkEssentials.DoSomething
.
This example will chain the execution of your DoSomething
logic from top to bottom (from most derived to least derived). It is just as easy to chain the execution from bottom to top, simply call the base implementation before instead of after the logic specific to each class.
UPDATE
You could arguably abuse a little the type system to get the behaviour you want with the following pattern:
public class Essentials
{
private void DoSomething()
{
//doing base stuff...
}
public class NetworkEssentials : Essentials
{
public void DoNetworkSomething()
{
//doing something
base.DoSomething(); //Perfectly OK
}
}
}
public class SomeClass : Essentials.NetworkEssentials
{
public void DoSomeSomething()
{
base.DoSomething(); //Compile time error
}
}
This really whole setup looks wierd but I have very little information to asses if this is really justified.
Upvotes: 1
Reputation: 1497
You can add a new implementation for whatever method from the base that you want to override. In this case you can have a new implementation for Dosomething in networkessentials and any derived class call to that method will only go through the NetworkEssentials. It wont stop you from calling the method but you can stop it from making the call directly to the base class which in essence is what you are trying to do I guess
public class Essentials
{
public void DoSomething()
{
//doing base stuff...
}
}
public class NetworkEssentials : Essentials
{
public void DoNetworkSomething()
{
//doing something
}
protected new void DoSomething()
{
}
}
public class someClass : NetworkEssentials
{
public void DoSomeSomething()
{
base.DoSomething(); //This will go thru NetworkEssentials and not directly to Dosomething
}
}
Upvotes: 1
Reputation: 100527
I think you are looking for virtual
- if you override method in derived class than children of that derived class will only be able to call derived's implementation (and there is absolutely no way to call top level one):
public class Essentials
{
virtual public void DoSomething()
{
//doing base stuff...
}
}
public class NetworkEssentials : Essentials
{
override public void DoSomething()
{
base.DoSomething();
// and other struff
}
public void DoNetworkSomething()
{
//doing something
}
}
public class someClass : NetworkEssentials
{
public void DoSomeSomething()
{
// can ONLY call nearest parent's that implements DoSomething
// so next calls NetworkEssentials.DoSomething
base.DoSomething();
}
}
Upvotes: 1
Reputation: 61349
No, with that inheritance structure you can't do that. As @MobyDisk noted, you may consider using composition instead of inheritance to accomplish this task.
You can mark methods as protected
to restrict access to only derived classes, but there is no way to force derived classes of derived classes to not have access.
Makes sense, really. If you have an Animal
with an Eat
method, Dog
would have access to that, and so should Beagle
(which would derive from Dog
).
Even using method hiding doesn't work.
public class Essentials
{
protected void DoSomething()
{
//doing base stuff...
}
}
public class NetworkEssentials : Essentials
{
public void DoNetworkSomething()
{
//doing something
}
private new void DoSomething()
{
}
}
public class someClass : NetworkEssentials
{
public void DoSomeSomething()
{
base.DoSomething(); //The thing I would like to prevent
}
}
Compiles just fine.
Upvotes: 0